python-3.x - 类方法重新定义, 'self' 参数问题

标签 python-3.x class self

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

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()

它返回一个错误,表示我需要在 self.some_method() 行中提供 self 作为参数:

TypeError: my_print() missing 1 required positional argument: 'self'

为什么会发生这种情况,也许有人知道解决这个问题的技巧?

最佳答案

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

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

但是,当在实例上找到该方法时(它隐藏了上的方法),绑定(bind)不会发生:

>>> 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 example():

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

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

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

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

关于python-3.x - 类方法重新定义, 'self' 参数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71292923/

相关文章:

python - 如何通过 C API 终止 python 脚本

python - 如何让字典值枚举的行为类似于Python中的字典键枚举?

python-3.x - 如何从Python容器内部访问kube-apiserver?

ruby-on-rails - before_create 仍然保存

使用 self 的 C 结构

python-3.x - Python 3.10 中 ffprobe 的困难

c++ - 类复制构造不能有类类型的参数

ios - 在 "class func"方法中获取 Swift 类名

包含 std::vector 的 C++ 模板

c++ - 在 C++ 中初始化为自身的对象