为什么自我被自动传递给实例化后在对象上设置的方法?

Bun*_*bit 10 python

 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将为您创建方法.


克里斯摩根提出了一个答案,显示这一个在行动.这是件好事.


Chr*_*gan 7

(这可以作为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)