site-packages/django/utils/functional.py
1 defNew_method_proxy (func):2 defInner (self, *args):3 ifself_wrapped isEmpty:4 Self._setup ()5 returnFunc (self._wrapped, *args)6 returnInner7 8 classLazyobject (object):9 """Ten A Wrapper for another class The can is used to delay instantiation of the wrapped class. One A by subclassing, you had the opportunity to intercept and alter the - instantiation. If you don ' t need to do, use Simplelazyobject. - """ the - #Avoid Infinite recursion when tracing __init__ (#19456). -_wrapped =None - + def __init__(self): -self._wrapped =Empty + A __getattr__=new_method_proxy (getattr) at - def __setattr__(self, Name, value): - ifName = ="_wrapped": - #Assign to __dict__ to avoid infinite __setattr__ loops. -Self.__dict__["_wrapped"] =value - Else: in ifself._wrapped isEmpty: - Self._setup () to setattr (self._wrapped, name, value) + - def __delattr__(self, name): the ifName = ="_wrapped": * RaiseTypeError ("can ' t delete _wrapped.") $ ifself._wrapped isEmpty:Panax Notoginseng Self._setup () - delattr (self._wrapped, name) the + def_setup (self): A """ the must is implemented by subclasses to initialize the wrapped object. + """ - RaiseNotimplementederror ('subclasses of Lazyobject must provide a _setup () method') $ $ #Because We have messed with __class__ below, we confuse pickle as to what - #class we are pickling. We ' re going to initialize the wrapped - #object to successfully pickle it, so we might as well just pickle the the #wrapped object since they ' re supposed to act the same. - #Wuyi #Unfortunately, if we try to simply act like the wrapped object, the ruse the #When would break , Pickle gets our ID (). Thus we end up with pickle - #thinking, in effect, that we is a distinct object from the wrapped Wu #object, but with the same __dict__. This can cause problems (see #25389). - # About #So instead, we define our own __reduce__ method and custom Unpickler. We $ #Pickle The wrapped object as the Unpickler ' s argument, so that pickle - #Would pickle it normally, and then the Unpickler simply returns its - #argument. - def __reduce__(self): A ifself._wrapped isEmpty: + Self._setup () the return(Unpickle_lazyobject, (self._wrapped,)) - $ #We have the explicitly override __getstate__ so, older versions of the #pickle don ' t try to pickle the __dict__ (which in the case of a the #Simplelazyobject may contain a lambda). The value would end up being the #ignored by our __reduce__ and custom Unpickler. the def __getstate__(self): - return {} in the def __deepcopy__(Self, Memo): the ifself._wrapped isEmpty: About #We have a to use type (self), not self.__class__, because the the #latter is proxied. theresult =type (self) () theMemo[id (self)] =result + returnresult - returnCopy.deepcopy (self._wrapped, Memo)
Good Code Series (i): Lazyobject