首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在类方法上使用property()

在类方法上使用property()
EN

Stack Overflow用户
提问于 2008-09-25 01:37:11
回答 10查看 110.5K关注 0票数 221

我有一个包含两个类方法的类(使用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()函数与@classmethod修饰函数一起使用吗?

EN

回答 10

Stack Overflow用户

发布于 2009-11-26 08:58:18

Python >= 3.9

只需同时使用两个装饰器即可。参见this answer

Python < 3.9

属性是在类上创建的,但会影响实例。因此,如果您需要一个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

或者,使用Python3的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
票数 132
EN

Stack Overflow用户

发布于 2012-11-29 19:32:12

我希望这个非常简单的只读@classproperty装饰器能帮助寻找类属性的人。

class classproperty(object):

    def __init__(self, fget):
        self.fget = fget

    def __get__(self, owner_self, owner_cls):
        return self.fget(owner_cls)

class C(object):

    @classproperty
    def x(cls):
        return 1

assert C.x == 1
assert C().x == 1
票数 70
EN

Stack Overflow用户

发布于 2010-03-30 18:07:36

如果你想通过实例化的对象访问class属性,那么只在meta类上设置它是没有帮助的,在这种情况下,你还需要在对象上安装一个普通属性(它会分派给class属性)。我认为下面的内容会更清楚一些:

#!/usr/bin/python

class classproperty(property):
    def __get__(self, obj, type_):
        return self.fget.__get__(None, type_)()

    def __set__(self, obj, value):
        cls = type(obj)
        return self.fset.__get__(None, cls)(value)

class A (object):

    _foo = 1

    @classproperty
    @classmethod
    def foo(cls):
        return cls._foo

    @foo.setter
    @classmethod
    def foo(cls, value):
        cls.foo = value

a = A()

print a.foo

b = A()

print b.foo

b.foo = 5

print a.foo

A.foo = 10

print b.foo

print A.foo
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/128573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档