最简单的方法, 就是采用如下方法:
- def create_class(class_name):
- if class_name == "MyClass":
- class MyClass():
- pass
- return MyClass
- else:
- class OtherClasss():
- pass
return OtherClasss
但是此类方法, 不能称之为真正的动态, 因为只能支持有限的类的创建, 那有什么方法, 能真正实现动态创建一些类呢? 所以, 这里就不得不提到关键词 type 了, 首先, 我们大多数人谈起 type, 首先想到的是, type 不就是用来测试变量类型的嘛, 如下:
- >>> print type(1)<type 'int'
- >>>> print type("1")<type 'str'
- >>>> class A():
- ... pass
- ...
- >>> type(A)<type 'classobj'
- >>>> type(A())
- <type 'instance'>
但是与此同时, type 还有另一个神奇的能力, 就是它也能动态的创建类. type 可以接受一个类的相关信息作为参数, 然后返回一个类. 下面是其用法:
type(类名, 父类的元组, 包含属性的字典)
什么是元类?
上面提到了类是一种特殊的对象, 对象就必须有类来创建, 而元类, 就是用来创建这种类的. 简单来说, 用于创建类的类, 就是元类. 可以理解为一下这种方式:
MyClass = MetaClass()
MyObject = MyClass()
而 type, 就是元类, 于是创建一个类, 就可以使用如下这种方式:
MyClass = type("MyClass", (), {})
MyObject = MyClass()
类的_metaclass_属性
当我们创建一个类的时候为其添加__metaclass__属性:
- class Foo(object):
- __metaclass__ = something...
[...]
那么, Python 就会采用你指定的方法, 来创建这个类, 否则, 会使用 type 来创建这个类, 下面演示如何自定义的指定 metaclass 属性:
- def lower_attr(class_name, class_parents, class_attr):
- lower_attr = {}
- for name, val in class_attr.items():
- if name.startswith('__'):
- lower_attr[name] = val
- else:
- lower_attr[name.lower()] = val
- return type(class_name, class_parents, lower_attr)
- class MyClss():
- __metaclass__ = lower_attr
- A = 'A'
- b = 'b'
- my_class = MyClss()
- print hasattr(my_class, 'A') # False
- print hasattr(my_class, 'b') # True
- print hasattr(my_class, 'a') # True
如何自己实现 ORM?
首先来定义 Field 类, 它负责保存数据库表的字段名和字段的类型:
- class Field(object):
- def __init__(self, name, column_type):
- self.name = name
self.column_type = column_type
在 Field 的基础上, 进一步定义各种具体类型的 Field, 比如 StringField,IntegerField 等等:
- class StringField(Field):
- def __init__(self, name, max_length):
- super(StringField, self).__init__(name, 'varchar(%d)' % max_length)
- class IntegerField(Field):
- def __init__(self, name):
super(IntegerField, self).__init__(name, 'int')
下一步, 就是编写最复杂的 ModelMetaclass 了:
- class ModelMetaclass(type):
- def __new__(cls, name, bases, attrs):
- if name == 'Model':
- return type.__new__(cls, name, bases, attrs)
- print('Found model: %s' % name)
- mappings = dict()
- for k, v in attrs.items():
- if isinstance(v, Field):
- mappings[k] = v
- for k in mappings.keys():
- attrs.pop(k)
- attrs['__mappings__'] = mappings
- attrs['__table__'] = name
return type.__new__(cls, name, bases, attrs)
以及基类 Model:
- class Model(dict, metaclass=ModelMetaclass):
- def __init__(self, **kw):
- super(Model, self).__init__(**kw)
- def __getattr__(self, key):
- try:
- return self[key]
- except KeyError:
- raise AttributeError(r"'Model' object has no attribute '%s'" % key)
- def __setattr__(self, key, value):
- self[key] = value
- def save(self):
- fields = []
- params = []
- args = []
- for k, v in self.__mappings__.items():
- fields.append(v.name)
- params.append('?')
- args.append(getattr(self, k, None))
- sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
- print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
创建 User 类, 并调用 save 方法, 保存:
- class User(Model):
- id = IntegerField('id')
- name = StringField('username', max_length=48)
- email = StringField('email', max_length=128)
- password = StringField('password', max_length=24)
- # 创建一个实例:
- u = User(id=12345, name='xiaoming', email='xiaoming@xiaomi.com', password='test')
- # 保存到数据库:
u.save()
上面, 我们就简单实现了一个 ORM.
参考链接
- Stack Overflow:
- https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python
来源: https://juejin.im/post/5c24957f518825650f047333