无法向classmethods添加属性

2024-06-07 17:17:10 发布

您现在位置:Python中文网/ 问答频道 /正文

以下代码段将导致AttributeError: 'classmethod' object has no attribute 'val'。你知道为什么和如何解决这个问题吗?在

class App(object):
    @classmethod
    def cfn(kls, *args):
        print kls, args
    cfn.val = 10

Tags: noappobjectdef代码段argsattributeval
2条回答

实际上,可以向类方法添加自定义属性。在

NB仅在python3.4上测试过

TL;DR

class classmethod_with_custom_attribute(object):
    def __init__(self, val):
        self.val = val

    def __call__(self, func):
        def wrapped_func(*args, **kwargs):
            return func(*args, **kwargs)
        wrapped_func.val = self.val
        wrapped_func = classmethod(wrapped_func)
        return wrapped_func

class App(object):
    @classmethod_with_custom_attribute(val=10)
    def cfn(cls, *args):
        print(cls, args)

说明

首先,您必须了解decorator是如何工作的,因为classmethod是一个decorator。在

写作

^{pr2}$

实际上和写作是一样的

def cfn(cls, *args):
    print(cls, *args)
cfn = classmethod(cfn)

现在,如果您尝试向方法添加属性,请不要将其编写为

@classmethod
def cfn(cls, *args):
    print(cls, *args)
cfn.val = 10

因为它相当于

def cfn(cls, *args):
    print(cls, *args)
cfn = classmethod(cfn)
cfn.val = 10

因此,您将属性添加到decorator返回的方法,而不是实际的方法。简单的解决方案是将属性添加到方法中,然后在该属性之后对其进行装饰:

def cfn(cls, *args):
    print(cls, *args)
cfn.val = 10
cfn = classmethod(cfn)

通过这种方式,可以装饰已经附加了属性的方法,而且显然decorator返回了相同的方法对象,这样就不会丢失属性。 我们都同意这种语法不是很好也不好读。保留decorator语法更好。您可以将所有逻辑放入自定义装饰器中,如下所示:

class classmethod_with_custom_attribute(object):
    def __init__(self, val):
        self.val = val

    def __call__(self, func):
        def wrapped_func(*args, **kwargs):
            return func(*args, **kwargs)
        wrapped_func.val = self.val
        wrapped_func = classmethod(wrapped_func)
        return wrapped_func

这里我们做同样的事情,注意在调用类方法decorator之前,分配了自定义属性的部分。现在我们可以像这样使用装饰器:

@classmethod_with_custom_attribute(val=10)
def cfn(cls, *args):
    print(cls, args)

现在你可以打电话了

App.cfn.val

它会像预期的那样工作

类方法根本不支持向它们添加任意属性。最好的办法是将要放入类方法属性中的数据放到其他地方。在

相关问题 更多 >

    热门问题