# -*- encoding: utf-8 -*-
import json
'''
第34条: 用元类来注册子类
关键:
1 元类
作用: 在程序中自动注册类型,对于需要反向查询的场合有用。
可以在简单的标示符与对应的类之间建立映射关系。
应用场景:
1) 将python对象表示为JSON格式的序列化数据,即
将指定对象转换成JSON字符串。
2) 开发者继承某个类的时候,程序自动调用registerCLass方法
,并将新的子类注册好。
原因: 定义完子类的class语句体后,元类可以拦截这个新的子类,
就可以注册新的类型
2 元类中注册子类的用法
示例:
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
# 获取新的类后,注册该类
registerClass(cls)
return cls
class RegisteredSerializable(BetterSerializable):
__metaclass__ = Meta
class Vector3D(RegisteredSerializable):
def __init__(self, x, y, z):
super(Vector3D, self).__init__(
x, y, z
)
self.x = x
self.y = y
self.z = z
def useMetaclass2():
v3 = Vector3D(1, 2, 3)
print "Before: {value}".format(
value=v3
)
data = v3.serialize()
print "Serialized: {value}".format(
value=data
)
after = deserialize(data)
print "After: {value}, type: {mytype}".format(
value=after,
mytype=type(after)
)
分析:
1) 元类必须继承万物之祖 type
2)注意元类的type.__new__(meta, name, bases, class_dict)返回的就是我们的类这个类型
3 总结
1) 类的注册是很有用的模式,
2) 设置元类中可以返回获取的新的类的时候,进行注册
(实际就是设置: <类名, 类> 的字典)
从基类中指定元类为刚才编写的元类,那么子类继承基类的时候,
就可以自动注册子类了
参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''
class Serializable(object):
def __init__(self, *args):
self.args = args
def serialize(self):
return json.dumps({"args": self.args})
class Point2D(Serializable):
def __init__(self, x, y):
super(Point2D, self).__init__(x, y)
self.x = x
self.y = y
def repr(self):
return "Point2D(%d, %d)" % (self.x, self.y)
class Deserializable(Serializable):
@classmethod
def deserialize(cls, jsonData):
params = json.loads(jsonData)
return cls(*params['args'])
class BetterPoint2D(Deserializable):
pass
class BetterSerializable(object):
def __init__(self, *args):
self.args = args
def serialize(self):
# 把序列化对象的类名写道JSON数据里面
return json.dumps(
{
'class': self.__class__.__name__,
'args': self.args
}
)
def __repr__(self):
return "args: {args}".format(args=self.args)
registry = {}
'''
建立: <类名,类>的映射,用于后续根据序列化的数据建立类的实例
'''
def registerClass(targetClass):
registry[targetClass.__name__] = targetClass
def deserialize(data):
params = json.loads(data)
name = params['class']
targetClass = registry[name]
return targetClass(*params['args'])
class EvenBetterPoint2D(BetterSerializable):
def __init__(self, x, y):
super(EvenBetterPoint2D, self).__init__(x, y)
self.x = x
self.y = y
def useMetaclass():
point = Point2D(5, 3)
print "Object: {point}".format(point=point)
print "Serialized: {point}".format(point=point.serialize())
point = BetterPoint2D(5, 3)
print "Before: {value}".format(value=point)
data = point.serialize()
print "Serialized: {value}".format(
value=data
)
after = BetterPoint2D.deserialize(data)
print "After: {value}".format(
value=after
)
print "##################### registry class"
registerClass(EvenBetterPoint2D)
point = EvenBetterPoint2D(5, 3)
print "Before: {point}".format(point=point)
data = point.serialize()
print "Serialized: {data}".format(data=data)
after = deserialize(data)
print "After: {after}, type: {value}".format(
after=after, value=type(after))
'''
注意: 元类必须继承自万物之祖type
'''
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
# 获取新的类后,注册该类
registerClass(cls)
return cls
class RegisteredSerializable(BetterSerializable):
__metaclass__ = Meta
class Vector3D(RegisteredSerializable):
def __init__(self, x, y, z):
super(Vector3D, self).__init__(
x, y, z
)
self.x = x
self.y = y
self.z = z
def useMetaclass2():
v3 = Vector3D(1, 2, 3)
print "Before: {value}".format(
value=v3
)
data = v3.serialize()
print "Serialized: {value}".format(
value=data
)
after = deserialize(data)
print "After: {value}, type: {mytype}".format(
value=after,
mytype=type(after)
)
def process():
useMetaclass2()
if __name__ == "__main__":
process()
Effective Python 读书笔记: 第34条: 用元类来注册子类
猜你喜欢
转载自blog.csdn.net/qingyuanluofeng/article/details/88936862
今日推荐
周排行