答案是“是的,但是……”
最好的理解方法是实际尝试:
>>> class RLCN:
... static_var = 5
... def method1(self):
... RLCN.static_var += 1
... def method2(self):
... self.static_var += 1
>>> rlcn = RLCN()
>>> RLCN.static_var, rlcn.static_var
(5, 5)
>>> rlcn.static_var
5
>>> rlcn.method1()
>>> RLCN.static_var, rlcn.static_var
(6, 6)
>>> rlcn.method2()
>>> RLCN.static_var, rlcn.static_var
(6, 7)
发生了什么?
嗯,访问通过self 的类属性工作得很好。如果没有同名的实例属性,则获取类属性。
但是分配给它会隐藏具有同名新实例属性的类属性。这可能不是您想要的。
请注意,这意味着您可以将类属性用作实例属性的“默认值”或“初始值”。但我不确定这样做是否非常Pythonic。实际发生的事情与新手(尤其是来自 C++11 或 Java 等领域的人)认为正在发生的事情非常不同。
(当你处理描述符时,事情会稍微复杂一些,比如方法或@propertys,但我们忽略它;在你讨论的简单情况下,它是不相关的。)
我宁愿做类似 class(self).static_var += 1 之类的东西,因为长名称不可读。
可以,只需拼写正确即可:type 是返回任何对象类型的函数。所以:
type(self).static_var += 1
这具有动态的附加优势(例如,当您有多重继承并且不知道 @property 来自哪一侧时,您可能不想显式列出类名,因为基本相同您想使用super() 而不是显式调用基类方法的原因)。
这有一个缺点是不能在 Python 2.x 中处理旧式类,但无论如何你都不应该使用它们。特别是在需要类属性的类中,因为这些正是您以后经常想要添加@classmethods、@propertys 等的类型,而这些都不适用于旧式类(以及许多其他东西)。如果您出于某种原因确实需要透明地处理旧式和新式类,self.__class__ 可用于旧式类。我不确定它是否能保证与新式课程一起使用;文档说type(object) 的返回值“通常与object.__class__ 返回的对象相同”,但没有说明“通常”在什么情况下是不真实的。它还在 3.x 中记录为 special attribute "added by the implementation" for "several object types"。在实践中,我不知道它们在 3.x 中有什么不同的情况,而在 2.x 中,它们不同的最突出的情况是旧式类。