在Python中将方法从一个类安全地绑定到另一个类

Oz1*_*123 6 python oop monkeypatching python-3.x

我知道我可以将一个函数附加到一个类并使其成为一个方法:

 >>> def is_not_bound(inst, name):
...     print("Hello %s" % name)
... 
>>> 
>>> class NoMethods:
...     pass
... 
>>> 
>>> setattr(NoMethods, 'bound', is_not_bound)
>>> 
>>> NoMethods().bound("oz") # prints: Hello oz
Hello oz
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这也适用于从一个类到另一个类的绑定方法:

>>> class Foo:
...     def foo(self, name):
...         print("Hello %s" % name)
... 
>>> class B:
...     pass
... 
>>> setattr(B, 'bound_to_b', getattr(Foo, 'foo'))
>>> B().bound_to_b("confused?")
Hello confused?
>>> 
Run Code Online (Sandbox Code Playgroud)

我能安全地使用它吗?有什么我在监督的吗?

更新

我发现的一个警告:

>>> B.bound_to_b
<function Foo.foo at 0x7fc997e8b730>
Run Code Online (Sandbox Code Playgroud)

虽然我从B调用了这个方法,但它似乎与Foo有关.

而且更令人惊讶的是:

>>> def new_method(self, addto):
...     return self.num + addto
... 
>>> setattr(B, 'add', new_method)
>>> b=B()
>>> b.num = 2
>>> b.add(2)
4
Run Code Online (Sandbox Code Playgroud)

Oz1*_*123 1

显然,这是有意为之的行为(这很酷!)。但显然,这种行为并不是很熟悉。

如果您了解 Python 2 很长时间,您可能不会意识到 Python 3 没有方法(如上所述)。

所以在 Python 3 中:

>>> class Foo:
...     def foo(self, name):
...         print("Hello %s" % name)
... 
>>> Foo.foo
<function Foo.foo at 0x7f729a406730>
>>> def foo():
...     pass
... 
>>> foo
<function foo at 0x7f729b83ff28>
>>> 
>>> Foo.foo
<function Foo.foo at 0x7f729a406730>
Run Code Online (Sandbox Code Playgroud)

没有什么区别!然而在 Python 2 中:

Python 2.7.14 (default, Feb  2 2018, 02:17:12) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo:
...     def foo(self, name):
...         print("Hello %s" % name)
... 
>>> Foo.foo
<unbound method Foo.foo>
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 我不明白这个答案的意义。您所做的就是重复[我链接的问题]中已经解释过的事情(/sf/ask/836486591/ Between-a-function-an -未绑定方法和绑定方法)。如果_this_回答了您的问题,为什么不直接将重复项标记为已接受呢? (3认同)