猴子补丁方法和参考的问题
我想知道是否有人可以解释并提供此问题的解决方案:
$ cat object-override-methods.py
class A:
def foo(self):
return 1
class B:
def foo(self):
return 1
for klass in A, B:
orig_foo = klass.foo
def foo(self):
return orig_foo(self) * 2
klass.foo = foo
A().foo()
B().foo()
$ python object-override-methods.py
Traceback (most recent call last):
File "object-override-methods.py", line 15, in <module>
A().foo()
File "object-override-methods.py", line 12, in foo
return orig_foo(self) * 2
TypeError: unbound method foo() must be called with B instance as first argument (got A instance instead)
提前致谢。
I was wondering if anyone could explain and offer a solution to this issue:
$ cat object-override-methods.py
class A:
def foo(self):
return 1
class B:
def foo(self):
return 1
for klass in A, B:
orig_foo = klass.foo
def foo(self):
return orig_foo(self) * 2
klass.foo = foo
A().foo()
B().foo()
$ python object-override-methods.py
Traceback (most recent call last):
File "object-override-methods.py", line 15, in <module>
A().foo()
File "object-override-methods.py", line 12, in foo
return orig_foo(self) * 2
TypeError: unbound method foo() must be called with B instance as first argument (got A instance instead)
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
orig_foo 是一个全局变量,每次通过循环都会改变值。循环完成后,
orig_foo
引用B.foo
。内部函数
foo
(一个或每个通过循环)在调用时都使用orig_foo
的全局值。所以他们都调用B.foo(self)
。当调用像
orig_foo
这样的“未绑定方法”时,Python2会检查第一个参数是否是适当类的实例。A().foo()
未通过此检查。 (有趣的是,这个检查在 Python3 中被删除,因此不会引发 TypeError,并且这个 bug 可能会变得更难发现。)要解决这个问题,您必须将
orig_foo
的值绑定到适当的 <代码>类。您可以通过将
orig_foo
设置为foo
的局部变量来实现这一点。一种方法是使用默认值使orig_foo
成为foo
的参数。 Python 在定义函数时绑定默认值。因此,orig_foo=orig_foo
将局部变量orig_foo
绑定到klass.foo
的当前值:orig_foo
is a global variable which changes value with each pass through the loop. After the loop is done,orig_foo
refers toB.foo
.The inner functions
foo
(one or each pass through the loop) both use the global value fororig_foo
when they are called. So they both callB.foo(self)
.When calling an "unbound method" like
orig_foo
, Python2 checks that the first argument is an instance of the appropriate class.A().foo()
does not pass this check. (Interestingly, this check was removed in Python3, so there would be no TypeError raised, and this bug may become harder to find.)To fix this, you must bind the value of
orig_foo
to the appropriateklass
.You can do that by making
orig_foo
a local variable offoo
. One way to do that is to makeorig_foo
an argument offoo
with a default value. Python binds default values at the time a function is defined. Soorig_foo=orig_foo
binds the local variableorig_foo
to the current value of theklass.foo
:因为
orig_foo
是在全局范围内定义的,所以每次循环都会践踏它的值。然后,每个新的foo
方法都会共享该被践踏的值。一个简单的解决方法是将代码移至函数中,如下所示:
这确保每个新的
foo
方法都获得其自己的orig_foo
值。Because
orig_foo
is defined at global scope, you're trampling on its value each time round the loop. That trampled value is then shared by each of your newfoo
methods.A simple fix is to move the code into a function, like this:
That ensures that each new
foo
method gets its own value oforig_foo
.