Python3 元类(metaclass)
1. 类也是对象
- 赋值给一个变量
- 可以作为参数进行传递
- 可以动态增加它的属性
- 可以拷贝
class ObjectClass(object):
pass
valObj = ObjectClass # 可以赋值
obj1 = ObjectClass()
obj2 = valObj()
print(obj1, obj2)
def testfunc(obj): # 可以作为参数传递
return obj()
obj3 = testfunc(ObjectClass)
print(obj3)
print(hasattr(ObjectClass, 'new_attr'))
ObjectClass.new_attr = 'Megvii' # 可以动态的增加属性
print(hasattr(ObjectClass, 'new_attr'))
import copy
ObjcetC_C = copy.copy(ObjectClass) # 可以拷贝
print(ObjcetC_C)
print(ObjcetC_C is ObjectClass)
<__main__.ObjectClass object at 0x1023a45f8> <__main__.ObjectClass object at 0x1023a4518>
<__main__.ObjectClass object at 0x102371f98>
False
True
<class '__main__.ObjectClass'>
True
那么就有一个问题了:既然 类本身是一个对象,那这个对象是谁创建的????
obj4 = ObjectClass()
print(obj4)
大概我们都知道这句话干了什么:将一个类(ObjectClass)实例化(创建一个对象)的过程。 那么也就是说,class关键字会在Python解释器解释到这里的时候创建一个对象(ObjectClass),而这个对象,拥有一个其他的一般对象没有的能力: 创建一个新的对象。
2. type 这个类
print(type('hello world'))
print(type(123456))
print(type(obj4))
<class 'str'>
<class 'int'>
<class '__main__.ObjectClass'>
我们会用 type() 来查看一个对象的类型,这是我们最常见的用法
newObject = type('newObject', (), {})
print(newObject)
obj5 = newObject()
print(obj5)
<class '__main__.newObject'> <__main__.newObject object at 0x102371198>
到这里,我们知道了这些东西:
- 类是一个对象
- type 可以创建类
- type 创建的对象拥有创建对象的能力(也就是类)
type 就是 Python 中所有类的元类(metaclass)
3. metaclass
元类 并不是某一个类的名字,它是一个概念,是一种Python的思想。
def MetaClass(name, bases, attrs):
attrs['Author']='Megvii'
return type(name, bases, attrs)
class InsClass(object, metaclass=MetaClass):
Imethod='InsClass'
def __init__(self, param):
self.__param = param
obj6 = InsClass('test_instance')
print(obj6.Author)
print(dir(obj6))
Megvii
['Author', 'Imethod', '_InsClass__param', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
元类 metaclass 就是用来创建一个对象的,如果我们自定义元类,就可以将创建对象的过程拦截下来,从而对这个对象进行自定义。
道生一,一生二,二生三,三生万物
道是 type 一是 metaclass 二是类 三是对象 对象就是 Python 的所有
3.How && When
Singleton mode
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
class Foo(metaclass=Singleton):
def __init__(self):
self.author = 'Megvii'
foo1=Foo()
foo2=Foo()
print(foo1 is foo2)
foo1.author = 'MEGVII'
print(foo2.author)
True
MEGVII
4. ORM (Object Relational Mapping)
首先定义 Field 类,它是所有 Fields 的父类
class Field(object):
def __init__(self, name, col_type):
self.name = name
self.col_type = col_type
def __str__(self):
return "<{0}:{1}>".format(self.__class__.__name__, self.name)
派生出其他的 Field 类型,假定只有 CharField(字符串类型) 和 IntegerField(整数类型) 两种
class CharField(Field):
def __init__(self, name, col_type='varchar(100)'):
super(CharField, self).__init__(name, col_type)
class IntegerField(Field):
def __init__(self, name, col_type='bigint'):
super(IntegerField, self).__init__(name, col_type)
自定义元类,控制 Model 的创建过程
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
if name == 'Model':
return super(ModelMetaClass, cls).__new__(cls, name, bases, attrs)
mappings = dict()
for key, val in attrs.items():
if isinstance(val, Field):
mappings[key] = val
for key in mappings.keys():
attrs.pop(key) # 防止字段污染类属性本身
attrs['__table__'] = name # 保存表名为类名
attrs['__mappings__'] = mappings # 添加映射关系
return super(ModelMetaClass, cls).__new__(cls, name, bases, attrs)
定义 Model 类,作为所有 Model 的父类
class Model(dict, metaclass=ModelMetaClass): # 本质是一个自定义的 dict 类
def __init__(self, **kwargs):
super(Model, self).__init__(**kwargs)
def __getattr__(self, key):
try:
return self[key]
except Exception:
raise AttributeError("'Model' object has no attribute {0}".format(key))
def __setattr__(self, key, value):
self[key] = value
def sql_(self):
fields = []
args = []
for k, v in self.__mappings__.items():
fields.append(v.name)
args.append(getattr(self, k, None))
return "INSERT INTO {table} ({fi}) VALUES ({va})".format(
table=self.__table__,
fi=', '.join(fields),
va=', '.join(args)
)
def save(self):
return self.sql_()
class User(Model):
uid = IntegerField('uid')
name = CharField('name')
user = User(uid='102740', name='zhangbo')
print(user.save())
print(dir(user))
INSERT INTO User (uid, name) VALUES (102740, zhangbo)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mappings__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__table__', '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'save', 'setdefault', 'sql_', 'update', 'values']