1.元类的定义
Python定义元类时,需要从type
类中继承,然后重写__new__
方法,便可以实现意想不到的功能。
class Meta(type):
def __new__(meta,name,bases,class_dict):
#...各种逻辑实现1
cls = type.__new__(meta,name,bases,class_dict)
#...各种逻辑实现2
return cls
class MyClass(object,metaclass=Meta):
stuff = 33
def foo(self):
pass
2.元类的本质
在Python当中万物皆对象,我们用class
关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,元类可以简称为类的类,元类的主要目的是为了控制类的创建行为。
-
type
是Python的一个内建元类,用来直接控制生成类,在Python中任何class
定义的类其实都是type
类实例化的结果。 -
只有继承了
type
类才能称之为一个元类,否则就是一个普通的自定义类,自定义元类可以控制类的产生过程,类的产生过程其实就是元类的调用过程。
3.元类验证子类
案例1:编写一个多边形类,当边数小于3
时,其类报错,实现其验证逻辑。
class ValidatePolygon(type):
## __new__当中放入验证逻辑
def __new__(meta,name,bases,class_dict):
if bases!=(object,): ##针对子类而不对基类
if class_dict['sides'] < 3:
raise ValueError('Polygons need 3+ sides')
return type.__new__(meta,name,bases,class_dict)
class Polygons(object,metaclass=ValidatePolygon):
sides = None
@classmethod
def interior_angles(cls):
return (cls.sides - 2) * 180
class Triangle(Polygons):
sides = 3
### 类设计报错。
class Line(Polygons):
sides = 1
4.元类注册子类
元类还有一个用途,就是在程序中自动注册类型
。开发者每次从基类中继承子类时,基类的元类都可以自动运行注册代码。
案例2:实现对象的序列化与反序列化
###建立类名与该类对象的映射关系,维护registry字典。
registry = {}
def register_class(target_class):
registry[target_class.__name__] = target_class
def deserialize(data):
params = json.loads(data)
name = params['class']
target_class = registry[name]
return target_class
class Meta(type):
def __new__(meta,name,bases,class_dict):
cls = type.__new__(meta,name,bases,class_dict)
register_class(cls) ##注册子类
return cls
class BetterSerializable(object):
def __init__(self,*args):
self.args = args
def serialize(self):
return json.dumps({
'class':self.__class__.__name__,
'args':self.args,
}
)
def __repr__(self):
# ...
class RegisterSerializabel(BetterSerializable,metaclass=Meta):
pass
通过元类来实现类的注册,可以确保所有的子类都不会遗漏,从而避免后续的错误。
5.总结
元类的各种操作可以实现类的验证和注册逻辑,均可以在元类的__new__
方法中实现,主要原因是当子类对象构建时,会先调用元类的__new__
方法,产生一个空对象,然后再调用子类的__init__
方法给对象属性进行赋值。