在类方法上使用 property() [英] Using property() on classmethods

查看:19
本文介绍了在类方法上使用 property()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

class Foo(object):_var = 5@类方法def getvar(cls):返回 cls._var@类方法def setvar(cls, value):cls._var = 值var = 属性(getvar,setvar)

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

<预><代码>>>>f = Foo()>>>f.getvar()5>>>f.setvar(4)>>>f.getvar()4>>>变量回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 ?类型错误:classmethod"对象不可调用>>>f.var=5回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 ?类型错误:classmethod"对象不可调用

是否可以将 property() 函数与 @classmethod 修饰函数一起使用?

解决方案

Python >= 3.9

只需将两个装饰器一起使用即可.请参阅此答案.

Python <3.9

属性是在类上创建的,但会影响实例.因此,如果您想要一个 classmethod 属性,请在元类上创建该属性.

<预><代码>>>>类 foo(对象):... _var = 5... class __metaclass__(type): # 元类的 Python 2 语法... 经过... @classmethod... def getvar(cls):...返回 cls._var... @classmethod... def setvar(cls, value):... cls._var = 值...>>>foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)>>>变量5>>>foo.var = 3>>>变量3

但是由于您无论如何都在使用元类,如果您只是将类方法移到那里,它会读起来更好.

<预><代码>>>>类 foo(对象):... _var = 5... class __metaclass__(type): # 元类的 Python 2 语法... @财产... def var(cls):...返回 cls._var... @var.setter... def var(cls, value):... cls._var = 值...>>>变量5>>>foo.var = 3>>>变量3

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

<预><代码>>>>类 foo_meta(类型):... def __init__(cls, *args, **kwargs):... cls._var = 5... @财产... def var(cls):...返回 cls._var... @var.setter... def var(cls, value):... cls._var = 值...>>>类 foo(元类 = foo_meta):... 经过...>>>变量5>>>foo.var = 3>>>变量3

I have a class with two class methods (using the classmethod() function) for getting and setting what is essentially a static variable. I tried to use the property() function with these, but it results in an error. I was able to reproduce the error with the following in the interpreter:

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

I can demonstrate the class methods, but they don't work as properties:

>>> 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

Is it possible to use the property() function with @classmethod decorated functions?

解决方案

Python >= 3.9

Just use both decorators together. See this answer.

Python < 3.9

A property is created on a class but affects an instance. So if you want a classmethod property, create the property on the metaclass.

>>> 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

But since you're using a metaclass anyway, it will read better if you just move the classmethods in there.

>>> 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

or, using Python 3's metaclass=... syntax, and the metaclass defined outside of the foo class body, and the metaclass responsible for setting the initial value of _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

这篇关于在类方法上使用 property()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆