2013-05-30 109 views
3

有這樣的代碼:從類和從該類的實例訪問功能

class B: 
    def f(self): 
     pass 

print(B.f) # <function B.f at 0xb711977c> 
print(B().f) # <bound method B.f of <__main__.B object at 0xb71774cc>> 

如何翻譯知道,當功能f從類對象訪問,然後返回正常的功能,但是當這個功能是從訪問類實例然後綁定方法返回?我讀到有一個__get__函數用於將對象與函數綁定,但是這對於類和類實例在內部是如何工作的?

+3

該機制被稱爲「描述符」:http://docs.python.org/2/howto/descriptor.html。儘管這是一個粗糙的實現細節。 – millimoose

回答

1

功能實現爲descriptors。引用文檔:

一般來說,描述符是具有「綁定行爲」的對象屬性,其屬性訪問已被描述符協議中的方法覆蓋。這些方法是__get__()__set__()__delete__()。如果爲某個對象定義了這些方法中的任何一種,則稱它爲描述符。

的想法是,__get__方法允許識別屬性是如何獲取的。考慮一個簡單的例子:

>>> class Descriptor(object): 
...  def __get__(self, obj, type=None): 
...   print '__get__(%r, %r)' % (obj, type) 
... 
>>> class A(object): 
...  desc = Descriptor() 
... 
>>> A.desc 
__get__(None, <class '__main__.A'>) 
>>> A().desc 
__get__(<__main__.A object at 0x020F5B50>, <class '__main__.A'>) 

正如你所看到的,並且在__get__ documentation所述,obj參數允許區分通過類或實例屬性的訪問。 Python內部可以使用相同的機制在訪問函數屬性時返回綁定或非綁定方法。

在實踐中:

>>> class A: 
...  def f(self): 
...    pass 
... 
>>> A.f.__get__(None, A) 
<unbound method A.f> 
>>> A.f.__get__(A(), A) 
<bound method A.f of <__main__.A instance at 0x022082D8>> 

這是所有的Python 2.x的例子,但據我所知,事情工作爲Python 3.x的相同,只是未綁定的方法是定期的功能。