简体   繁体   English

Python中的类属性

[英]Class attributes in Python

Is there any difference in the following two pieces of code? 以下两段代码有什么区别? If not, is one preferred over the other? 如果不是,是否首选另一种? Why would we be allowed to create class attributes dynamically? 为什么允许我们动态创建类属性?

Snippet 1 片段1

class Test(object):
    def setClassAttribute(self):
        Test.classAttribute = "Class Attribute"

Test().setClassAttribute()

Snippet 2 片段2

class Test(object):
    classAttribute = "Class Attribute"

Test()

First, setting a class attribute on an instance method is a weird thing to do. 首先,在实例方法上设置类属性是一件很奇怪的事情。 And ignoring the self parameter and going right to Test is another weird thing to do, unless you specifically want all subclasses to share a single value.* 除非您特别希望所有子类共享一个值,否则忽略self参数并直接进行Test是另一件事。

* If you did specifically want all subclasses to share a single value, I'd make it a @staticmethod with no params (and set it on Test ). *如果您确实确实希望所有子类共享一个值,则将其@staticmethod为不带参数的@staticmethod方法(并在Test上进行设置)。 But in that case it isn't even really being used as a class attribute, and might work better as a module global, with a free function to set it. 但是在那种情况下,它甚至没有真正用作类属性,并且可能作为全局模块更好地工作,并带有一个自由函数来对其进行设置。

So, even if you wanted to go with the first version, I'd write it like this: 因此,即使您想使用第一个版本,我也会这样写:

class Test(object):
    @classmethod
    def setClassAttribute(cls):
        cls.classAttribute = "Class Attribute"

Test.setClassAttribute()

However, all that being said, I think the second is far more pythonic. 但是,话虽这么说,我认为第二个要比Pythonic多得多。 Here are the considerations: 这里是注意事项:

  • In general, getters and setters are strongly discouraged in Python. 通常,强烈建议不要在Python中使用getter和setter。
  • The first one leaves a gap during which the class exists but has no attribute. 第一个留下空白,在该空白中类存在但没有属性。
  • Simple is better than complex. 简单胜于复杂。

The one thing to keep in mind is that part of the reason getters and setters are unnecessary in Python is that you can always replace an attribute with a @property if you later need it to be computed, validated, etc. With a class attribute, that's not quite as perfect a solution—but it's usually good enough. 要记住的一件事是,在Python中不需要getter和setter的部分原因是,如果以后需要计算,验证等内容时,总是可以用@property替换属性。使用class属性,那并不是一个完美的解决方案,但通常已经足够了。


One last thing: class attributes (and class methods, except for alternate constructor) are often a sign of a non-pythonic design at a higher level. 最后一件事:类属性(以及类方法,除了备用构造函数之外)通常是更高层次上非Python设计的标志。 Not always , of course, but often enough that it's worth explaining out loud why you think you need a class attribute and making sure it makes sense. 当然,并非总是如此 ,但经常足够,因此有必要大声解释为什么您认为需要类属性并确保它有意义。 (And if you've ever programmed in a language whose idioms make extensive use of class attributes—especially if it's Java—go find someone who's never used Java and try to explain it to him.) (并且,如果您曾经使用过使用习惯用法广泛使用类属性的语言进行编程,尤其是使用Java的话,那就去找一个从未使用过Java的人,然后尝试向他解释一下。)

It's more natural to do it like #2, but notice that they do different things. 像#2一样自然而然地做,但是请注意,他们做不同的事情。 With #2, the class always has the attribute. 对于#2,类始终具有属性。 With #1, it won't have the attribute until you call setClassAttribute . 对于#1,只有在调用setClassAttribute ,它才会具有该属性。

You asked, "Why would we be allowed to create class attributes dynamically?" 您问:“为什么要允许我们动态创建类属性?” With Python, the question often is not "why would we be allowed to", but "why should we be prevented?" 使用Python,问题通常不是“为什么要被允许”,而是“为什么要被阻止?” A class is an object like any other, it has attributes. 类是一个像其他对象一样的对象,它具有属性。 Objects (generally) can get new attributes at any time. 对象(通常)可以随时获取新属性。 There's no reason to make a class be an exception to that rule. 没有理由使类成为该规则的例外。

I think #2 feels more natural. 我认为#2感觉更自然。 #1's implementation means that the attribute doesn't get set until an actual instance of the class gets created, which to me seems counterintuitive to what a class attribute (vs. object attribute) should be. #1的实现意味着,在创建该类的实际实例之前,不会设置该属性,在我看来,这与类属性(相对于对象属性)应具有的直觉背道而驰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM