python - 静态与类方法的类变量范围
问题描述
我在 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)
输出是1 1 2
。
这让我感到惊讶(我期待4 4 4
),我想知道为什么?
解决方案
当用@classmethod
第一个参数装饰cls
时inc_class(cls)
,就是类。<class '__main__.A'>
和<class '__main__.B'>
分别为A
和B
。socls._var
指的是A
's _var
,同样是 for B
。在inc_static
, 装饰@staticmethod
没有参数,你明确指的<class '__main__.Base'>
是不同的_var
.
注意's 和's'_var': 0
中的属性。正在做你期望它做的事情,将成员绑定到类,在这种情况下和.Base
A
__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})`
调用后Base.inc_static()
:
>>> 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})
调用后A.inc_class()
:
>>> 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})
有趣的是A
's_var
是如何初始化的。请注意,您cls._var += 1
之前所做cls._var
的已经定义。正如这里所解释的,cls._var += 1
相当于cls._var = cls._var; cls._var += 1
. 由于python 查找的方式,第一次读取cls._var
将失败A
并继续在Base
. 在赋值_var
被添加到A
's__dict__
的值Base._var
,然后一切都很好。
>>> 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})
推荐阅读
- r - 贝叶斯 Beta 回归模型 - jags 中的错误:无效的父值
- r - 如何改进我的代码以将因子列转换为 data.frame 中的列表?
- python-3.x - 在 pandas 中获取非结构化 df 列表并在两列中给出数据结构
- python - 如何使按钮必须是可点击的以更改值并在 PyQt 中继续?
- rest - Jenkins CORS 过滤器插件未添加 Access-Control-Allow-Origins 标头
- jasmine - 茉莉业力句柄GlobalErrors
- datetime - Neo4j 在不使用 apoc 插件的情况下将时间戳()纪元格式化为日期时间
- azure - 将 Azure DevOps 连接到 Azure AD 的电子邮件要求
- javascript - 在按钮单击时调用功能组件
- javascript - 将 Google 跟踪代码管理器与 gatsby-plugin-guess-js 集成