Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 静态与类方法的类变量范围_Python_Static Methods_Class Method_Class Variables - Fatal编程技术网

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 =

我在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 = 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()