猴子修补python类中的自引用

时间:2013-11-28 23:47:22

标签: javascript python

我试图在修补方法中理解 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有什么不同吗?

1 个答案:

答案 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的属性。

这有意义吗?