以下是我刚在机器上播放的示例:
$ 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?我需要做什么,才能在里面引用自我?
答案 0 :(得分: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
吗?
答案 1 :(得分: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
传递给函数。