任务简单的介绍是: 在新风格对象模型中,Python操做实际上是在类中查找特殊方法的(经典对象是在实例中进行操做的),如今须要将一些新风格的实例包装到代理中,,此代理能够选择将一些特殊的方法委托给内部的被包装对象。python
代码实施为:缓存
1 class Proxy(object): 2 """全部代理的基类""" 3 def __init__(self, obj): 4 super(Proxy, self).__init__() #少了此补会致使无限递归循环 5 self._obj = obj 6 7 def __getattr__(self, attribute): 8 return getattr(self._obj, attribute) 9 10 11 def make_binder(unbound_method): 12 def wrapper(self, *arg, **kwargs): 13 return unbound_method(self._obj, *arg, **kwargs) 14 return wrapper 15 16 17 known_proxy_classes = {} 18 19 20 def proxy(obj, *specials): 21 """工厂函数""" 22 obj_cls = obj.__class__ 23 key = obj_cls, specials 24 cls = known_proxy_classes.get(key) 25 if cls is None: 26 cls = type("%sProxy" % ob_cls.__name, (Proxy,), {}) 27 for name in specials: 28 name = '__%s__' % name 29 unbound_method = getattr(obj_cls, name) 30 setattr(cls, name, make_binder(unbound_method)) 31 """缓存之以供进一步使用 32 known_proxy_classes[key] = cls 33 """实例化并返回须要的代理 34 return cls(obj)
代理(以及自动托管)都得归功于__getattr__机制,在查询任何属性时,(包括方法,python并不区分二者),python都会自动调用__getattr__。app
代码运行结果以下图:函数
其实结果很容易理解,就是经过特殊方法代理实现子类方法的代理,例如上面实例,因为代理了list中的len和iter,那么能够实现方法len以及迭代,没有代理geiitem方法,那么在利用index时就会报错。spa
在新风格对象中,python操做并不会在运行的时候查找特殊方法:它们依赖于类对象的“槽”。而这些槽会在对象被建立或者修改的时候更新,所以,对于一个代理对象,若是它要把特殊方法托管给被封装的对象,它自己必须属于某个量身定作的类。代理