我试图在修补方法中理解 self 引用。代码如下:
class foo():
def __init__(self):
self.child = lambda: none
self.child.string = "child's string value"
self.string = "string value 1"
print "initialized"
def func1(self):
print self.string
if __name__=="__main__":
foo0=foo()
foo0.newMethod = lambda: "test"
print foo0.newMethod()
foo0.func1()
foo0.child.secondMethod = foo0.func1
foo0.child.secondMethod()
为什么孩子的方法将 self 引用到foo0?这和javascript有什么不同吗?
答案 0 :(得分:1)
该问题的答案在于Python在未绑定方法和绑定方法之间的区别。当你定义一个方法时,它是 unbound :它可以在类的任何实例上运行,实际上它只不过是一个第一个参数名为self的函数(即便如此,它也是一个约定)和一点点检查,所以你不要与他们做真正可怕的事情。
class Foo(object):
def my_method(self, arg):
print "self:", self
print "arg:", arg
a = Foo()
print Foo.my_method(a, 2)
# self: self: <__main__.Foo object at 0x000000000219DE10>
# arg: 2
# You could, in theory, do that, but Python complains because it values the sanity
# of the people who will have to maintain your code :p
print Foo.my_method(1, 2)
# TypeError: unbound method my_method() must be called with Foo instance as first argument (got int instance instead)
到目前为止,没什么特别的。但是,当我们调用一个不在类本身上的方法时(如上所述),但在该类的实例(即在一个对象上)上,Python有一些魔力。
a.my_method(2)
# self: <__main__.Foo object at 0x000000000219DE10>
# arg: 2
注意突然你只需要向方法提供arg
,即使它是用两个参数定义的吗?这是因为a.my_method
是绑定方法:它是my_method
对象的a
方法,而不是{{1}的方法} class 。它绑定到该特定实例,并在其中引用该特定对象(如果您查看Foo
,您会注意到它具有dir(a.my_method)
属性。)
但是,在您的示例中,如果您要在im_self
中添加print self
语句,则会打印func1
而不是foo0
。那是因为“绑定”不是在你调用方法(foo0.child
)时发生的,而是在你引用它时foo0.child.secondMethod()
)。
更重要的是,它只会在您引用您在类上定义的方法时发生。
因此,在您的示例中,foo0.func1
引用了foo0.child.secondMethod = foo0.func1
的{{1}}方法(它为您提供了foo0
的绑定方法),但在分配中没有执行任何魔术本身。它只是设置func1
的属性。
这有意义吗?