2013-06-18 84 views
4

這裏我只是通過發揮我的機器上的例子:覆蓋的方法不包含自我?

$ python 
Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
[GCC 4.7.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
# just a test class 
>>> class A(object): 
... def hi(self): 
...  print("hi") 
... 
>>> a = A() 
>>> a.hi() 
hi 
>>> def hello(self): 
... print("hello") 
... 
>>> 
>>> hello(None) 
hello 
>>> 
>>> 
>>> 
>>> a.hi = hello 
# now I would expect for hi to work the same way as before 
# and it just prints hello instead of hi. 
>>> a.hi() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: hello() takes exactly 1 argument (0 given) 
>>> 
>>> def hello(): 
... print("hello") 
... 
# but instead this one works, which doesn't contain any 
# reference to self 
>>> a.hi = hello 
>>> a.hi() 
hello 
>>> 
>>> 
>>> 
>>> 
>>> a.hello = hello 
>>> a.hello() 
hello 

這到底是怎麼回事?當它用作方法時,爲什麼函數不會獲得參數self?我需要做些什麼來獲得對自我的引用?

回答

8

在通過一個實例中引用的類中的方法綁定到實例,你的情況:

In [3]: a.hi 
Out[3]: <bound method A.hi of <__main__.A object at 0x218ab10>> 

對比:

In [4]: A.hi 
Out[4]: <unbound method A.hi> 

那麼,要實現你可能想要的效果,不要

In [5]: def hello(self): 
    ...:  print "hello" 
    ...:  

In [6]: A.hi = hello 

In [7]: a.hi() 
hello 

當心 - 這將適用於A所有實例。但是如果你只想在一個實例上覆蓋一個方法,你真的需要通過self

+0

一個很好的例子,「我已經知道,但不知何故不適用於當前的情況」。感謝您清理它。 – erikbwork

3

這是功能被訪問的方式,當他們是類屬性。

作爲類別屬性添加的函數被作爲descriptor訪問。你看,如果你做

class A(object): 
    pass 

def f(*a): pass 
A.f = f 
print f 
print A.f 
print A().f 

在這裏,你得到的輸出

<function f at 0x00F03D70> 
<unbound method A.f> 
<bound method A.f of <__main__.A object at 0x00F089D0>> 

同樣的輸出你與

print f 
print f.__get__(None, A) 
print f.__get__(A(), A) 

得到,因爲這是如何描述符的工作方式。

所有這些 - 通過描述符協議從函數到方法的轉換 - 不會發生在實例屬性上。

如果你

a = A() 
a.f = f 

然後a.f的那樣好讀回的功能,而不是一個方法。因此,你應該在你做任務和時間考慮這個而做

a.f = lambda: f(a) 

爲了通過a的功能。

+0

感謝您鏈接到綁定方法的實際工作方式_explanation_。 – Koterpillar