Python 静态与类方法的类变量范围
我在python类变量上发现了一种奇怪的行为(至少对我来说是奇怪的)Python 静态与类方法的类变量范围,python,static-methods,class-method,class-variables,Python,Static Methods,Class Method,Class Variables,我在python类变量上发现了一种奇怪的行为(至少对我来说是奇怪的) class Base(object): _var = 0 @classmethod def inc_class(cls): cls._var += 1 @staticmethod def inc_static(): Base._var += 1 class A(Base): pass class B(Base): pass a =
class Base(object):
_var = 0
@classmethod
def inc_class(cls):
cls._var += 1
@staticmethod
def inc_static():
Base._var += 1
class A(Base):
pass
class B(Base):
pass
a = A()
b = B()
a.inc_class()
b.inc_class()
a.inc_static()
b.inc_static()
print(a._var)
print(b._var)
print(Base._var)
输出为12
这让我很惊讶(我期待
4
),我想知道为什么?当用@classmethod
修饰时,cls
到inc_class(cls)
的第一个参数是类<代码>和
分别用于A
和B
。因此cls.\u var
指A
的\u var
,与B
类似。在用@staticmethod
修饰的inc\u static
中,没有参数,您明确地指的是一个不同的\u var
请注意“变量”:0
属性位于Base
和A
的\uu dict
中@classmethod
正在做您期望它做的事情,将成员绑定到类,在本例中是A
和B
>>> Base.__dict__
mappingproxy({'__module__': '__main__', '_var': 0, 'inc_class': <classmethod
object at 0x7f23037a8b38>, 'inc_static': <staticmethod object at
0x7f23037a8c18>, '__dict__': <attribute '__dict__' of 'Base' objects>,
'__weakref__': <attribute '__weakref__' of 'Base' objects>, '__doc__': None})
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__doc__': None})`
调用A.inc\u class()
后:
尽管这两个类继承自基类,但它们是完全不同的对象。通过实例化
a
和b
,您有两个属于两个独立类的对象。当你打电话的时候
a.inc_class()
b.inc_class()
将类A的\u var
属性增加一次,然后对类B执行相同的操作。尽管它们共享相同的名称,但它们是不同的对象。如果您有类a的第二个实例,比如说a2
,并且您将再次调用该函数,那么两个调用都将操作相同的变量。这解释了如何获得前两个输出
第三个输出引用基类对象。同样,尽管它是相同的名称,但它是一个不同的对象。您将第三个对象增加两次,因此您得到的答案是
2
。如果您不告诉我们您感到惊讶的内容,将很难帮助您解决问题。抱歉,可能会重复,但我没有找到关于建议重复线程的问题的任何答案。重复的目的是给出相同的答案。问一个重复的问题并不是得到已经被问过的问题答案的最佳方式;好处是。我的问题是关于类变量,而不是类和静态方法。让我发疯的是:如果我写“@classmethod def inc_class(cls):cls.\u var\u boom+=1”,我会出错,因此python不会为该类实例创建新的“\u var\u boom”变量,而是为“\u var”创建新变量@cabbi我正在研究它,但是如果您尝试使用相同名称的未定义成员,则继承类似乎会接受基的成员。请注意,+=
需要一个现有的变量,因此它确实应该给出一个错误,除了\u var
之外,它从基中拾取它。解释它<代码>cls.\u var+=1
相当于cls.\u var=cls.\u var;cls.\u var+=1
。读取cls.\u var
将找到Base.\u var
并将其值分配给新定义的a.\u var
,然后+=
工作正常。我现在找不到Python如何进行名称查找的文档,但它的作用域可能会扩大,直到(如果)它找到它,这就是为什么Base.\u var
在A.\u var
被定义之前就被选中了。通过您上面的评论,您完全向我解释了“魔力”python正在处理这些变量。您最后的评论肯定应该是您答案的一部分
>>> Base.__dict__
mappingproxy({'__module__': '__main__', '_var': 1, 'inc_class':
<classmethod object at 0x7f23037a8b38>, 'inc_static': <staticmethod
object at 0x7f23037a8c18>, '__dict__': <attribute '__dict__' of 'Base'
objects>, '__weakref__': <attribute '__weakref__' of 'Base' objects>,
'__doc__': None})
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__doc__': None, '_var': 1})
>>> class Base(object):
... _var = 10
... @classmethod
... def inc_class(cls):
... cls._var += 1
...
>>> class A(Base):
... pass
...
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__doc__': None})
>>> A.inc_class()
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__doc__': None, '_var': 11})
a.inc_class()
b.inc_class()