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?我需要做什么才能在其中获得对 self 的引用?

4

2 回答 2

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. 但是如果你只想在一个实例上覆盖一个方法,你真的需要 passself吗?

于 2013-06-18T08:33:50.760 回答
3

当函数是类属性时,这是访问函数的方式。

作为类属性添加的函数作为描述符被访问。你会看到,如果你这样做

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

thena.f也可以作为函数读取,而不是作为方法读取。因此,您应该在做作业时考虑这一点,而不是做

a.f = lambda: f(a)

为了传递a给函数。

于 2013-06-18T08:35:18.330 回答