gpt4 book ai didi

Python:将函数作为类的方法调用

转载 作者:太空狗 更新时间:2023-10-30 01:55:14 25 4
gpt4 key购买 nike

让我们从一些代码开始:

def func(*x):
print('func:', x)


class ABC:
def __init__(self, f):
self.f1 = f

def f2(*x):
print('f2:', x)

现在我们做一些测试:

>>> a = ABC(func)
>>> a.f1(10)
func: (10,)
>>> a.f2(10)
f2: (<__main__.ABC object at 0xb75381cc>, 10)
>>> a.f3 = func
>>> a.f3(10)
func: (10,)
>>> a.f1
<function func at 0xb74911ec>
>>> a.f2
<bound method ABC.f2 of <__main__.ABC object at 0xb75381cc>>
>>> a.f3
<function func at 0xb74911ec>

请注意,func 是一个普通函数,我们将其设为类的方法 f1

我们可以看到 f2 将类实例作为第一个参数,但 f1f3 不是,即使所有函数被称为类方法。我们还可以看到,如果我们将普通函数作为类的方法来调用,Python 不会从中创建绑定(bind)方法。

那么为什么 f1f3 没有将类实例传递给它,即使我们将它作为类的方法调用?而且,Python 如何知道我们正在将外部函数作为方法调用,以便它不应该将实例传递给它。

-- 编辑 --

好的,基本上我做错的是我将函数附加到实例上而不是类对象本身。因此,这些功能简单地成为实例属性。我们可以通过以下方式检查:

>>> ABC.__dict__
... contents...
>>> a.__dict__
{'f1': <function func at 0xb74911ec>, 'f3': <function func at 0xb74911ec>}

另请注意,此字典不能分配给:

>>> ABC.__dict__['f4'] = func
TypeError: 'dict_proxy' object does not support item assignment

最佳答案

您通过检查对象部分地回答了您自己的问题。在 Python 中,对象的行为类似于命名空间,因此第一个属性指向一个函数,第二个属性指向一个方法。

这是动态添加方法的方法:

from types import MethodType

def func(*x):
print('func:', x)


class ABC:
def __init__(self, f):
self.f1 = MethodType(f, self, self.__class__)

def f2(*x):
print('f2:', x)

if __name__ == '__main__':
a = ABC(func)
print a.f1(10)
print a.f2(10)
a.f3 = MethodType(func, a, ABC)
print a.f3(10)

请注意,它将方法绑定(bind)到您的实例,而不是基类。为了monkeypatch ABC 类:

>>> ABC.f4 = MethodType(func, None, ABC)
>>> a.f4(1)
('func:', (<__main__.ABC instance at 0x02AA8AD0>, 1))

Monkeypatching 在 Python 圈子里通常不受欢迎,尽管它在其他动态语言中很流行(尤其是在 Ruby 中,当时该语言还很年轻)。

如果您曾经求助于这种强大但危险的技术,我的建议是:

  • 永远、永远不要覆盖现有的类方法。只是不要。

关于Python:将函数作为类的方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13524370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com