gpt4 book ai didi

python - 初始化对象时传递方法的最佳方式是什么

转载 作者:太空宇宙 更新时间:2023-11-04 09:39:09 26 4
gpt4 key购买 nike

我有一个代表数学模型的类。在这个类中,我有解决模型的方法、打印结果的方法等。

模型可以解决不同的功能。我想知道初始化 python 对象时传递方法的最佳方式是什么。

举个例子,假设我有类 Foo 和方法 f1。我的目标是 f1 不是在类定义中定义,而是作为参数传递。

所以,我知道我可以做到:

class Foo:
def __init__(self, x1):
self.x1 = x1

def f1(self):
return self.x1

bar = Foo(10)

print(bar.f1())
# Result: 10

但是有没有办法做到这一点:

class Foo:
def __init__(self, x1, f1):
self.x1 = x1
self.f1 = f1

def f_outside(self):
return self.x1

bar = Foo(10, f_outside)

print(bar.f1())
# Result: 10

最后一个代码示例不起作用。错误是:缺少 1 个必需的位置参数:'self'

最佳答案

是的,你可以这样做,因为方法只是绑定(bind)函数。

当你在一个实例上查找一个方法时(比如 bar.f1,注意,还没有调用)并且 Python 在实例上找到一个名为 f1 的函数class(不是实例本身),然后函数被绑定(bind),产生一个方法对象。 Python 使用 __get__ method为了这;函数定义该方法,并使用正确的参数调用它会生成一个方法。

但是,当您在实例上存储函数时,不会发生这种情况。它已经是实例的一部分,不需要绑定(bind),对吧?因此,当您使用 self.f1 = f1 时,不会发生任何绑定(bind)。调用 bar.f1() 将无法传入 self,因此会出现错误。

但是没有什么能阻止您自己绑定(bind)函数:

class Foo:
def __init__(self, x1, f1):
self.x1 = x1
self.f1 = f1.__get__(self)

现在 bar.f1() 可以工作了,因为 f1 已经绑定(bind)到 bar:

>>> class Foo:
... def __init__(self, x1, f1):
... self.x1 = x1
... self.f1 = f1.__get__(self)
...
>>> def f_outside(self):
... return self.x1
...
>>> bar = Foo(10, f_outside)
>>> bar.f1()
10

还有其他方法可以达到同样的效果;您可以存储使用 lambda 创建的函数以显式传入 self:

self.f1 = lambda: f1(self)

或者您可以使用 functools.partial()让它传入 self 的对象:

self.f1 = partial(f1, self)

或者您可以通过直接使用方法的类型对象来创建方法实例;通过 typing.MethodType 引用了类型:

self.f1 = MethodType(f1, self)

但最后一个将实现与 f1.__get__(self) 完全相同的事情。

如果您想深入了解绑定(bind)的更多信息,那么您需要阅读 descriptor HOWTO .

关于python - 初始化对象时传递方法的最佳方式是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52337183/

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