我想在类方法上使用 functools.partialmethod
。然而,我发现的行为并不是我所期望的(并且喜欢)。
这是一个例子:
class A(object):
@classmethod
def h(cls, x, y):
print(cls, x, y)
class B(A):
h = functools.partialmethod(A.h, "fixed")
当我这样做
>>> b = B()
>>> b.h(3)
我得到一个错误:
...
TypeError: h() takes 3 positional arguments but 4 were given
这符合
>>> b.h()
<class '__main__.A'> <__main__.B object at 0x1034739e8> fixed
但是,我希望(并希望)有以下行为:
>>> b.h(4)
<class '__main__.B'> fixed 4
我认为 functools.partialmethod
将 B.h
视为普通实例方法,并自动将实际实例作为第一个参数传递。
但是这种行为使得 functools.partialmethod
无法卡住继承类的类方法中的参数。
最佳答案
无需过多赘述,partial
对象与@classmethod
用于创建类实例的描述符协议(protocol)不能很好地融合。简单的解决方法是以通常的方式定义重写的方法:
class B(A):
@classmethod
def h(cls, y):
return A.h("fixed", y)
可能可以通过调用 partial
来做你想做的事,但我找不到它。以下是我的一些尝试,以及它们失败的原因。
A.h
调用函数对象的 __get__
方法,返回第一个参数已经绑定(bind)到调用类的函数。 partial
然后将该函数应用到 "fixed"
,但是随后生成的可调用 still 有一个 __get__
方法尝试将调用类插入到结果调用中。您可以尝试通过将 h
定义为实际的 static 方法来解决这个问题:
class B(A):
h = staticmethod(partial(A.h, "fixed"))
>>> B.h(4)
<class '__main__.A'> fixed 4
但是如您所见,您在调用 partial
时已经卡住了类参数。另一种尝试是通过直接访问参数来避免描述符协议(protocol):
class B(A):
h = staticmethod(partial(A.__dict__["h"], "fixed"))
但是 classmethod
对象实际上是不可调用的;只有它们的 __get__
方法的返回值是,所以调用 partial
失败。
关于python - functools.partialmethod 和 classmethod 的组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39332671/