如何制作一个类属性?
在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
我上面使用的语法是可能的还是需要更多的东西?
我想要类属性的原因是我可以延迟加载类属性,这似乎足够合理。
没有找到相关结果
已邀请:
7 个回复
遣莫捅炭
当我们打电话给
时,二传手没有工作,因为我们正在打电话
,不是
。 添加元类定义解决了这个问题:
现在一切都会好的。
肺鬼耙扮群
,那么您的示例将完全按照您的要求工作。
需要注意的是,您不能将其用于可写属性。当
将提高
,
将覆盖属性对象本身。
响摔衅幸
方法来覆盖调用类,
。我想知道在元类上使用
装饰器的操作是否类似。 (我之前没试过,但现在我好奇......) [更新:] 哇,确实有效:
注意:这是在Python 2.7中。 Python 3+使用不同的技术来声明元类。使用:
,删除
,其余部分相同。
壤欠攻混
这会让你获得Foo的一个类属性,但是有一个问题......
这到底是怎么回事?为什么我不能从实例到达类属性? 在找到我认为的答案之前,我在这方面打了很长时间。 Python @properties是描述符的子集,并且从描述符文档(强调我的): 属性访问的默认行为是获取,设置或删除 来自对象字典的属性。例如,
有一个查找链 从
开始,然后
,继续 通过
的基类除了元类。 因此,方法解析顺序不包括我们的类属性(或元类中定义的任何其他内容)。可以使内置属性装饰器的子类具有不同的行为,但是(引用需要)我已经得到了开发人员有一个很好的理由(我不明白)这样做的印象。 这并不意味着我们运气不好;我们可以很好地访问类本身的属性......我们可以在实例中从
获取类,我们可以使用它来创建@property调度程序:
现在
适用于班级和实例!如果派生类替换了它的底层
(这是最初让我参与此搜索的用例),它也将继续做正确的事情。 这对我来说并不是100%满足 - 不得不在元类和对象类中进行设置,感觉它违反了DRY原则。但后者只是一个单线调度员;我现在对它很好,如果你真的想要的话,你可以将它压缩成lambda或者其他东西。
犁攀富
现在正常创建您想要的实际类,除非它使用您在上面创建的元类。
如上所述,如果我们只在单个类上使用它,那么定义这个元类有点奇怪。在这种情况下,如果您使用的是Python 2样式,则可以在类主体中实际定义元类。这样它就没有在模块范围内定义。
补蹲农界维
但是元类方法看起来更清晰,并且具有更可预测的行为。 也许您正在寻找的是Singleton设计模式。关于在Python中实现共享状态有一个很好的SO QA。
呕蹿尉
这是所有答案中最好的: “metaproperty”被添加到类中,因此它仍然是实例的属性 不需要在任何类中重新定义thingy 该属性作为实例和类的“类属性” 您可以灵活地自定义_thingy的继承方式 在我的情况下,我实际上为每个孩子定制了
,而不是在每个类中定义它(并且没有默认值):