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