2017-10-18 136 views
0

这里瓦尔一个小例子代码:困惑静态类在python

class A: 
    staticvar=3; 

    def foo2(self): 
     print("------ Foo2") 
     print("static: "+str(A.staticvar)); 
     print("instance: "+ str(self.staticvar)); 

class B(A): 

    def setStaticVar(self, num): 
     B.staticvar=num; 


a=A(); 
b=B(); 

a.staticvar=7; 
a.foo2(); 

b.setStaticVar(100); 

a.foo2(); 

b.foo2(); 

什么结果:

------ 
static: 3 
instance: 7 -->correct. Instance var modified 
------ 
static: 3 
instance: 7 --> Not correct. Why static var is not 100 
------ 
static: 3 
instance: 100 --> Correct, but this value should be shared between A and B 

这究竟是为什么? A和B之间不应该共享静态变量?为什么当它在b到b中被修改时。从这个例子看来,每个类都有自己的静态变量(从我的角度来看,并不是真正的静态变量,因为只有一个静态变量,而且每个类只有一个静态变量)。

任何人都可以解释这种行为?

干杯。

回答

0

我怀疑你遇到的是名称解析问题。当你得到B.staticvar时,解释器无法找到它并退回到它的超类以尝试解析名称。在遍历到A后,解释器找到staticvar并返回该值。

当您设置一个值,B.staticvar,但是,你会得到许多相同的行为,你的“实例”的情况下,其中一个属性调用staticvar添加到B。现在,当它试图解析B(或其实例)上的属性名称时,它将使用这个新值,而不会回落到A。在Python中,继承一个类没有太多关于共享它的属性的知识,它是关于设置一个fallback类来解析名称,当它们没有在你的子类中定义时(因此为什么不需要明确地“覆盖”方法,以及为什么你必须记得在B.method_name内调用super(A).method_name,如果你想要运行父功能)。

为了得到你要求的行为,无论是在A定义setStaticVar,和/或改变其身体A.staticvar=num

+0

又是怎样呢,那只有一个静态无功的类可以通过A.被accesed类中的staticvar或self.staticvar?不应该在使用print(self.staticvar)时抛出错误,因为它无法解析实例var? – Notbad

+1

类实例上的名称解析从实例上开始,但后来回到类本身。例如,类的方法在类中定义,而不在其实例上定义,但可以在实例上调用它们。例如,给定'a = A()','a.setStaticVar(5)'解析为'A.setStaticVar(a,5)',实际上你可以写第二行,它的行为就是相同。同样,'staticvar'存在于'A'中,可以通过'a'访问,或者可以通过定义具有相同名称的'a'的属性来映射。 – scnerd

+1

一般来说,在像Python这样的动态类型语言中(我相信JS和类似语言也同样适用),纯粹用名称与值之间的映射关系来考虑“类”和“实例”与备份树如果名字在任何给定点都不能解决,你可以去。对象,类型,模块,甚至本地上下文(闭包)都只是可以嵌套在彼此之内的字典。你可以玩游戏来修改各种级别的字典,但对这种语言中的“静态”变量没有太多的想法。 – scnerd