class LazyObject(object): """ A wrapper for another class that can be used to delay instantiation of the wrapped class. By subclassing, you have the opportunity to intercept and alter the instantiation. If you don't need to do that, use SimpleLazyObject. """ # Avoid infinite recursion when tracing __init__ (#19456). _wrapped = None def __init__(self): self._wrapped = empty __getattr__ = new_method_proxy(getattr) def __setattr__(self, name, value): if name == "_wrapped": # Assign to __dict__ to avoid infinite __setattr__ loops. self.__dict__["_wrapped"] = value else: if self._wrapped is empty: self._setup() setattr(self._wrapped, name, value) def __delattr__(self, name): if name == "_wrapped": raise TypeError("can't delete _wrapped.") if self._wrapped is empty: self._setup() delattr(self._wrapped, name) def _setup(self): """ Must be implemented by subclasses to initialize the wrapped object. """ raise NotImplementedError('subclasses of LazyObject must provide a _setup() method')
从介绍来讲, 能够看出LazyObject的做用就是推迟包装类的实例化,便是须要用的时候,才实例化它。python
对于理解这段代码,能够从实际适用来入手。咱们只需指定一个要使用的类,传给LazyObject,那么咱们app
使用LazyObject,就如同使用包装类同样。这种设计,应该是对用户透明的。ide
当咱们使用类时,分为获取属性,添加属性,删除属性。函数
对应的三种方法,__getatrr__, __setatrr__, __delatrr__。oop
在python中对三种方法的重载,就能够实现上述的效果。即LazyObject与包装类是透明的。spa
在LazyObject的三种方法的实现中, 能够看出推迟实例化的实现。设计
即先判断包装类是否已经实例化,不然实例它(经过实现_setup()方法实现)。code
注意到__getattr__方法,是经过 new_method_proxy函数实现的。orm
new_method_proxy实际上是工厂函数。目的也是推迟实例化。ci
def new_method_proxy(func): def inner(self, *args): if self._wrapped is empty: self._setup() return func(self._wrapped, *args) return inner