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

Safely bind method from one class to another class in Python

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
8
9
10
11
12
 >>> 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

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

1
2
3
4
5
6
7
8
9
10
11
>>> 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?
>>>

我能安全使用这个吗?我在监督什么?

更新

我已经发现了一个警告:

1
2
>>> B.bound_to_b
<function Foo.foo at 0x7fc997e8b730>

尽管我从B调用了这个方法,但它似乎与foo绑定在一起。

更令人惊讶的是!:

1
2
3
4
5
6
7
8
>>> def new_method(self, addto):
...     return self.num + addto
...
>>> setattr(B, 'add', new_method)
>>> b=B()
>>> b.num = 2
>>> b.add(2)
4


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

如果您认识Python2很长时间了,您可能不知道Python3没有任何方法(如上所述)。

所以在Python 3中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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>

没有区别!但是,在Python2中:

1
2
3
4
5
6
7
8
9
10
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>
>>>