在类方法上使用property()

发布于 2021-02-02 23:10:09

我有一个带有两个类方法的类(使用classmethod()函数),用于获取和设置本质上是静态变量的东西。我试图将property()函数与这些函数一起使用,但会导致错误。我能够在解释器中使用以下代码重现该错误:

class Foo(object):
    _var = 5
    @classmethod
    def getvar(cls):
        return cls._var
    @classmethod
    def setvar(cls, value):
        cls._var = value
    var = property(getvar, setvar)

我可以演示类方法,但是它们不能用作属性:

>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable

是否可以将property()函数与类方法修饰的函数一起使用?

关注者
0
被浏览
77
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    属性是在类上创建的,但会影响实例。因此,如果要使用classmethod属性,请在元类上创建该属性。

    >>> class foo(object):
    ...     _var = 5
    ...     class __metaclass__(type):  # Python 2 syntax for metaclasses
    ...         pass
    ...     @classmethod
    ...     def getvar(cls):
    ...         return cls._var
    ...     @classmethod
    ...     def setvar(cls, value):
    ...         cls._var = value
    ...     
    >>> foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)
    >>> foo.var
    5
    >>> foo.var = 3
    >>> foo.var
    3
    

    但是由于无论如何都使用元类,因此只要将类方法移入其中,它就会更好看。

    >>> class foo(object):
    ...     _var = 5
    ...     class __metaclass__(type):  # Python 2 syntax for metaclasses
    ...         @property
    ...         def var(cls):
    ...             return cls._var
    ...         @var.setter
    ...         def var(cls, value):
    ...             cls._var = value
    ... 
    >>> foo.var
    5
    >>> foo.var = 3
    >>> foo.var
    3
    

    或者,使用Python 3的metaclass=...语法,在foo类主体外部定义的元类,以及负责设置初始值的元类_var:

    >>> class foo_meta(type):
    ...     def __init__(cls, *args, **kwargs):
    ...         cls._var = 5
    ...     @property
    ...     def var(cls):
    ...         return cls._var
    ...     @var.setter
    ...     def var(cls, value):
    ...         cls._var = value
    ...
    >>> class foo(metaclass=foo_meta):
    ...     pass
    ...
    >>> foo.var
    5
    >>> foo.var = 3
    >>> foo.var
    3
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看