前面說了descriptor,這個東西其實和Java的setter,getter有點像。但這個descriptor和上文中我們開始提到的函數方法這些東西有什么關系呢?
所有的函數都可以是descriptor,因為它有__get__方法。
代碼如下:
>>> def hello():
pass
>>> dir(hello)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '<span style="color: #ff0000;">__get__</span>
', '__getattribute__',
'__hash__', '__init__', '__module__', '__name__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>>
注意,函數對象沒有__set__和__del__方法,所以它是個non-data descriptor.
方法其實也是函數,如下:
代碼如下:
>>> class T(object):
def hello(self):
pass
>>> T.__dict__['hello']
<function hello at 0x00CD7EB0>
>>>
或者,我們可以把方法看成特殊的函數,只是它們存在于類 中,獲取函數屬性時,返回的不是函數本身(比如上面的<function hello at 0x00CD7EB0>),而是返回函數的__get__方法的返回值,接著上面類T的定義:
>>> T.hello 獲取T的hello屬性,根據查找策略,從T的__dict__中找到了,找到的是<function hello at 0x00CD7EB0>,但不會直接返回<function hello at 0x00CD7EB0>,因為它有__get__方法,所以返回的是調用它的__get__(None, T)的結果:一個unbound方法。
<unbound method T.hello>
>>> f = T.__dict__['hello'] #直接從T的__dict__中獲取hello,不會執行查找策略,直接返回了<function hello at 0x00CD7EB0>
代碼如下:
>>> f
<function hello at 0x00CD7EB0>
>>> t = T()
>>> t.hello #從實例獲取屬性,返回的是調用<function hello at 0x00CD7EB0>的__get__(t, T)的結果:一個bound方法。
代碼如下:
<bound method T.hello of <__main__.T object at 0x00CDAD10>>
>>>
為了證實我們上面的說法,在繼續下面的代碼(f還是上面的<function hello at 0x00CD7EB0>):
代碼如下:
>>> f.__get__(None, T)
<unbound method T.hello>
>>> f.__get__(t, T)
<bound method T.hello of <__main__.T object at 0x00CDAD10>>
新聞熱點
疑難解答