【问题标题】:Confused about static class vars in python对python中的静态类变量感到困惑
【发布时间】:2018-03-30 09:36:13
【问题描述】:

这里有一个小示例代码:

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修改。

从这个例子看来,每个类都有自己的静态变量(在我看来并不是真正的静态变量,因为只有一个静态变量,我们有 2 个,每个类一个)。

谁能解释这种行为?

干杯。

【问题讨论】:

    标签: python-3.x inheritance static-variables


    【解决方案1】:

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

    但是,当您将值设置为B.staticvar 时,您会得到与“实例”情况大致相同的行为,其中将名为staticvar 属性添加到B。现在,当它尝试解析B(或其实例)上的属性名称时,它会使用这个新值,而不会回退到A。在 Python 中,继承一个类并不是要共享它的属性,而是设置一个后备类来解析未在您的子类中定义的名称(因此为什么不需要显式“覆盖”方法,以及为什么您如果要运行父函数,必须记住在B.method_name 中调用super(A).method_name

    要获得您要求的行为,请在 A 中定义 setStaticVar,和/或将其正文更改为 A.staticvar=num

    【讨论】:

    • 那么,只有一个静态变量的类可以通过类中的 A.staticvar 或 self.staticvar 访问吗?使用 print(self.staticvar) 时不应该抛出错误,因为它无法解析实例变量吗?
    • 类实例的名称解析从实例开始,然后返回到类本身。例如,类的方法是在类上定义的,而不是在其实例上定义的,但您可以在实例上调用它们。例如,给定a = A()a.setStaticVar(5) 解析为A.setStaticVar(a, 5),实际上你可以只写第二行,它的行为会完全一样。同样,staticvar 存在于A 中,可以通过a 访问,也可以通过定义具有相同名称的a 属性来隐藏。
    • 一般来说,在像 Python 这样的动态类型语言中(我相信这在很大程度上适用于 JS 和类似语言),纯粹根据名称的映射来考虑“类”和“实例”如果名称在任何给定点无法解析,您可以转到带有备份树的值。对象、类型、模块,甚至本地上下文(闭包)都只是可以相互嵌套的字典。您可以玩游戏以在各个级别修改这些字典,但在这种语言中没有太多关于“静态”变量的概念。
    猜你喜欢
    • 2016-06-30
    • 1970-01-01
    • 2020-01-16
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 2017-03-13
    • 2017-11-11
    • 1970-01-01
    相关资源
    最近更新 更多