2013-06-18 2 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> 

Итак, для достижения эффекта вы, вероятно, хотите, do

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

Смежные вопросы