class Person():
pass;
def say_hi(self):
print 'hii'
me=Person()
me.say_hi=say_hi
me.say_hi()
Run Code Online (Sandbox Code Playgroud)
是不是在python中自动传递了self参数?为什么调用me.say_hi()给出堆栈跟踪?
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: say_hi() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)
aar*_*ing 13
它不是以你正在做的方式传递的.
你必须这样做.
import types
me.say_hi = types.MethodType(say_hi, me, Person)
Run Code Online (Sandbox Code Playgroud)
它的工作原理.
当python实例化一个类时,它基本上为每个类方法执行上述过程.当你按照你试图做的方式将一个方法"修补"到一个对象上时,它不是一个绑定方法,只是作为一个函数存在instance.__dict__.调用它与调用任何其他函数没什么不同.如果要在实例上粘贴方法,则必须手动使其成为如上所示的方法.
如果你这样做的话
class Person(object):
pass
def say_hi(self):
print 'hii'
Person.say_hi = say_hi
me = Person()
me.say_hi()
Run Code Online (Sandbox Code Playgroud)
然后它会工作,因为Python将为您创建方法.
克里斯摩根提出了一个答案,显示这一个在行动.这是件好事.
(这可以作为aaronasterling答案的一些示范.)
以下是定义:
>>> class Person(object):
... def bound(self):
... print "Hi, I'm bound."
...
>>> def unbound(self):
... print "Hi, I'm unbound."
...
Run Code Online (Sandbox Code Playgroud)
请注意这些方法和函数的类型.
>>> type(Person.bound)
<type 'instancemethod'>
>>> type(Person().bound)
<type 'instancemethod'>
>>> type(unbound)
<type 'function'>
>>> Person.unbound = unbound
Run Code Online (Sandbox Code Playgroud)
当它Person在实例化之前设置时,它就会被绑定.
>>> Person().bound()
Hi, I'm bound.
>>> Person().unbound()
Hi, I'm unbound.
Run Code Online (Sandbox Code Playgroud)
但是,如果它在实例化后设置,它仍然是'function'类型.
>>> me = Person()
>>> me.rebound = unbound
>>> type(me.rebound)
<type 'function'>
>>> type(me.unbound)
<type 'instancemethod'>
>>> me.rebound
<function unbound at 0x7fa05efac9b0>
>>> me.rebound()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)
'instancemethod'类型可用于将'function'绑定到对象.它在types模块中MethodType.
>>> import types
>>> me.rebound = types.MethodType(unbound, me, Person)
Run Code Online (Sandbox Code Playgroud)
现在它受到了正确的约束.
>>> type(me.rebound)
<type 'instancemethod'>
>>> me.rebound()
Hi, I'm unbound.
>>> # Not true any more!
Run Code Online (Sandbox Code Playgroud)