Class 方法重新定义,'self' 参数问题

Class methods redefining, 'self' argument problems

我想实现这种情况 - 我有一个 class,那里有一些包含外部方法的变量,在某些情况下可以重新定义方法。它可能看起来像:

def my_print(self):
    print('my print is called')

class example():
    some_method = my_print

    def __init__(self):
        self.some_method()

    def test(self):
        self.some_method()

所以,它有效:

a = example()
a.test()

结果如下:

my print is called (from init)
my print is called (from test)

但万一重新定义some_method:

a = example()
a.some_method = my_print
a.test()

它 returns 一个错误,它说我需要在行 self.some_method():

中给出 self 作为参数
TypeError: my_print() missing 1 required positional argument: 'self'

为什么会这样,也许有人知道解决这个问题的诀窍?

这是 . 在 Python 中的微妙之处。它既查找 class 上的方法,又 将方法绑定 到实例。此绑定是将 class 实例隐式提供为第一个参数 self 的原因。看看这个:

>>> print(example.some_method)
<function my_print at 0x7f66c4129f30>
>>> print(a.some_method)
<bound method my_print of <test.example object at 0x7f66c41c2290>>

但是,当在 实例 上找到方法时(隐藏 class 上的方法),绑定没有发生:

>>> a = example()
my print is called
>>> a.some_method = my_print
>>> print(a.some_method)
<function my_print at 0x7f66c4129f30>

这在Python reference中有说明:

It is also important to note that user-defined functions which are attributes of a class instance are not converted to bound methods; this only happens when the function is an attribute of the class.

那么,解决方案是确保该方法始终是 class 实例的属性,并相应地调用它:

class example():

    def __init__(self):
        self.some_method = my_print
        self.some_method(self)

    def test(self):
        self.some_method(self)

看起来很奇怪,效果很好。

如果您希望该方法始终是 class 的属性,请考虑使用继承。