在python中,我可以使用@classmethod装饰器向类中添加方法。是否有类似的装饰器可以将属性添加到类中?我可以更好地展示我在说什么。
class Example(object):
the_I = 10
def __init__( self ):
self.an_i = 20
@property
def i( self ):
return self.an_i
def inc_i( self ):
self.an_i += 1
# is this even possible?
@classproperty
def I( cls ):
return cls.the_I
@classmethod
def inc_I( cls ):
cls.the_I += 1
e = Example()
assert e.i == 20
e.inc_i()
assert e.i == 21
assert Example.I == 10
Example.inc_I()
assert Example.I == 11
我上面使用的语法是可能的还是需要更多的东西?
我需要类属性的原因是我可以延迟加载类属性,这似乎很合理。
如果您按如下方式定义classproperty,那么您的示例将完全按照您的要求工作。
class classproperty(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, owner):
return self.f(owner)
需要注意的是,您不能将此用于可写属性。While . i = 20将引发AttributeError, Example。I = 20将覆盖属性对象本身。
我碰巧想出了一个与@Andrew非常相似的解决方案,只是DRY
class MetaFoo(type):
def __new__(mc1, name, bases, nmspc):
nmspc.update({'thingy': MetaFoo.thingy})
return super(MetaFoo, mc1).__new__(mc1, name, bases, nmspc)
@property
def thingy(cls):
if not inspect.isclass(cls):
cls = type(cls)
return cls._thingy
@thingy.setter
def thingy(cls, value):
if not inspect.isclass(cls):
cls = type(cls)
cls._thingy = value
class Foo(metaclass=MetaFoo):
_thingy = 23
class Bar(Foo)
_thingy = 12
这是最好的答案:
“元属性”被添加到类中,因此它仍然是实例的属性
不需要在任何类中重新定义东西
该属性在实例和类中都作为“类属性”工作
您可以灵活地自定义_thingy的继承方式
在我的例子中,我实际上为每个子定制了_thingy,没有在每个类中定义它(并且没有默认值):
def __new__(mc1, name, bases, nmspc):
nmspc.update({'thingy': MetaFoo.services, '_thingy': None})
return super(MetaFoo, mc1).__new__(mc1, name, bases, nmspc)
如果您按如下方式定义classproperty,那么您的示例将完全按照您的要求工作。
class classproperty(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, owner):
return self.f(owner)
需要注意的是,您不能将此用于可写属性。While . i = 20将引发AttributeError, Example。I = 20将覆盖属性对象本身。