Когда украшено @classmethod
, первый аргумент cls
до inc_class(cls)
, ну, в общем, класс. <class '__main__.A'>
и <class '__main__.B'>
соответственно для A
и B
. Таким образом, cls._var
относится к A
_var
, и аналогично для B
. В inc_static
, украшенном @staticmethod
, аргумент отсутствует, вы явно ссылаетесь на <class '__main__.Base'>
, другой _var
.
Обратите внимание на атрибут '_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
1038 *. Обратите внимание, что вы делаете cls._var += 1
до того, как cls._var
было определено. Как объяснено здесь , cls._var += 1
эквивалентно cls._var = cls._var; cls._var += 1
. Из-за способа , в котором Python выполняет поиск , первое чтение cls._var
завершится неудачей в A
и продолжит находить его в Base
. При присвоении _var
добавляется A
__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})