1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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的作用就是推遲包裝類的實例化,即是需要用的時候,才實例化它。
對於理解這段代碼,可以從實際適用來入手。我們只需指定一個要使用的類,傳給LazyObject,那麼我們
使用LazyObject,就如同使用包裝類一樣。這種設計,應該是對用戶透明的。
當我們使用類時,分爲獲取屬性,添加屬性,刪除屬性。
對應的三種方法,__getatrr__, __setatrr__, __delatrr__。
在python中對三種方法的重載,就可以實現上述的效果。即LazyObject與包裝類是透明的。
在LazyObject的三種方法的實現中, 可以看出推遲實例化的實現。
即先判斷包裝類是否已經實例化,否則實例它(通過實現_setup()方法實現)。
注意到__getattr__方法,是通過 new_method_proxy函數實現的。
new_method_proxy其實是工廠函數。目的也是推遲實例化。
1
2
3
4
5
6
|
def new_method_proxy(func): def inner( self , * args): if self ._wrapped is empty: self ._setup() return func( self ._wrapped, * args) return inner |