class Person():
pass;
def say_hi(self):
print 'hii'
me=Person()
me.say_hi=say_hi
me.say_hi()
是不是在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)
答案 0 :(得分:13)
它不是以你正在做的方式传递的。
你必须这样做。
import types
me.say_hi = types.MethodType(say_hi, me, Person)
让它发挥作用。
当python实例化一个类时,它基本上为每个类方法执行上述过程。当你以一种尝试的方式将一个方法“修补”到一个对象上时,它不是一个绑定的方法,只是作为一个函数存在于instance.__dict__
中。调用它与调用任何其他函数没什么不同。如果要在实例上粘贴方法,则必须手动使其成为如上所示的方法。
如果你要做
class Person(object):
pass
def say_hi(self):
print 'hii'
Person.say_hi = say_hi
me = Person()
me.say_hi()
然后它会起作用,因为Python会为你创建方法。
克里斯·摩根(Chris Morgan)提出answer表明这一点正在行动中。这是件好事。
答案 1 :(得分:7)
(这可以作为aaronasterling答案的一些示范。)
以下是定义:
>>> class Person(object):
... def bound(self):
... print "Hi, I'm bound."
...
>>> def unbound(self):
... print "Hi, I'm unbound."
...
请注意这些方法和功能的类型。
>>> type(Person.bound)
<type 'instancemethod'>
>>> type(Person().bound)
<type 'instancemethod'>
>>> type(unbound)
<type 'function'>
>>> Person.unbound = unbound
在实例化之前在Person
上设置它时,它会被绑定。
>>> Person().bound()
Hi, I'm bound.
>>> Person().unbound()
Hi, I'm unbound.
但是,如果在实例化后设置,它仍然是'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)
'instancemethod'类型可用于将'function'绑定到对象。它位于types
模块中MethodType
。
>>> import types
>>> me.rebound = types.MethodType(unbound, me, Person)
现在它已经正确绑定了。
>>> type(me.rebound)
<type 'instancemethod'>
>>> me.rebound()
Hi, I'm unbound.
>>> # Not true any more!
答案 2 :(得分:3)
在这种情况下,say_hi不是你班级的方法。它只是对函数的引用。这就是自参数不会自动传递的原因。
或者只是使用:
class Person():
def say_hi(self):
print 'hii'
me=Person() me.say_hi=say_hi me.say_hi()
答案 3 :(得分:1)
自动传递方法的self参数。您没有方法,而是一个作为对象属性的函数。如果你做Person.say_hi = say_hi
,那么Person()。say_hi()将按预期工作。方法是一个函数,它是类的属性,而不是实例,而self只传递给方法。
类属性定义实例应该如何工作,而实例属性只是您访问的正常属性。这意味着从实例访问类属性时会修改它们(例如,将函数转换为方法),而实例属性保持不变。
>>> class A(object): pass
...
>>> def f(self): print self
...
>>> ob = A()
>>> A.f = f
>>> ob.g = f
>>> print ob.f
<bound method A.f of <__main__.A object at 0xb74204ec>>
>>> print ob.g
<function f at 0xb7412ae4>
>>> ob.f()
<__main__.A object at 0xb74204ec>
>>> ob.g('test')
test
由于A
是一个类,f
,A().f
和A.f
是不同的东西。由于ob
是一个对象,f
和ob.g
是相同的。
答案 4 :(得分:1)
因为函数say_hi()
没有在person类中定义,所以它不知道self
是什么,当你调用它时它没有将self
传递给方法。这就像调用静态方法一样。
你可以这样做
me=Person()
me.say_hi=say_hi
me.say_hi(me)
答案 5 :(得分:1)
不,self不会自动传递给对象,因为它尚未在类块中定义。相反,您已在错误的块中定义了一个函数say_hi。当你运行它时,在这个上下文中的'self'实际上是一个函数的第一个参数,它在类块之外,因此不是类的一部分,因此就是错误。
答案 6 :(得分:0)
我想你想这样做
say_hi(me)
但编程OO的常用方法是:
class Person:
def say_hi(self):
print 'hii'
me = Person()
me.say_hi()
答案 7 :(得分:0)
也许这有用吗?
class Person():
def say_hi(self):
print 'hii'
me=Person()
me.say_hi()
我把这个函数放在了类中,因为我觉得那就是你想要的。然后你可以稍后从类对象我调用它。