2

我想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对于冻结继承类的类方法中的参数毫无用处。

4

2 回答 2

2

无需过多详细说明,该对象与用于创建类实例partial的描述符协议不能很好地混合。@classmethod简单的解决方法是以通常的方式定义您的覆盖方法:

class B(A):
    @classmethod
    def h(cls, y):
        return A.h("fixed", y)

可以通过调用 来做你想做的事partial但我找不到它。以下是我的一些尝试,以及它们失败的原因。

A.h调用__get__函数对象的方法,返回第一个参数已经绑定到调用类的函数。partial然后将该函数应用于"fixed",但生成的可调用对象仍然具有一个__get__方法,该方法尝试将调用类插入到生成的调用中。您可以尝试通过定义h实际上是静态方法来解决这个问题:

class B(A):
    h = staticmethod(partial(A.h, "fixed"))

>>> B.h(4)
<class '__main__.A'> fixed 4

但是正如你所看到的,当你调用partial. 另一种尝试是通过直接访问参数来避免描述符协议:

class B(A):
    h = staticmethod(partial(A.__dict__["h"], "fixed"))

classmethod对象实际上是不可调用的;只有他们的方法的返回值__get__是,所以调用partial失败。

于 2016-09-05T14:57:17.503 回答
1

使用super(v2.7)

class A(object):
    @classmethod
    def c(cls, x, y):
        print('cls:{}, x:{}, y:{}'.format(cls, x, y))

class B(A):
    def c(self, y):
        super(B, self).c(x = 'fixed', y = y) 

class C(A):
    def c(self, x):
        super(C, self).c(x = x, y = 'fixed') 

b = B()
c = C()

>>> 
>>> b.c(4)
cls:<class '__main__.B'>, x:fixed, y:4
>>> c.c(4)
cls:<class '__main__.C'>, x:4, y:fixed
>>> 

超级是超级

于 2016-09-05T15:03:52.707 回答