Почему переменная класса доступна в экземпляре без префикса __class__? - PullRequest
0 голосов
/ 03 августа 2010

См. Пример ниже.Использование префикса __class__ с экземпляром класса «object» дает ожидаемый результат.Почему переменная класса доступна даже в экземпляре класса c () без префикса __class__?В какой ситуации он используется?

>>> class c:
        x=0


>>> c.x
0
>>> c().x
0
>>> c().__class__.x
0
>>> c.x += 1
>>> c.x
1
>>> c().x += 1
>>> c.x
1
>>> c().__class__.x += 1
>>> c.x
2
>>> 

1 Ответ

2 голосов
/ 03 августа 2010

Почему переменная класса даже доступно в экземпляре класса 'c ()' без префикса class ?

Вы можете с пользой думать об этом как об экземплярах, "наследующих" от своего класса. IOW, когда атрибут с именем 'atr' ищется в экземпляре x (например, x.atr), если он не найден в самом экземпляре, он затем ищется в классе (что, в свою очередь, может вызвать поиск в базах класса) вверх по цепочке mro).

В какой ситуации он используется?

Самый распространенный случай:

class sic(object):
  def foo(self): ...

x = sic()
x.foo()

Вы не можете думать о foo как о «переменной класса», но это потому, что термин «переменная» действительно бессмыслен в Python, который скорее имеет дело с names и attribute . В данной лексической области не существует отдельного пространства имен для вызываемых и не подлежащих вызову объектов: все они совместно используют одинаковое пространство имен.

Так, например, если вы сделали x.foo = 23, вы больше не могли бы звонить x.foo() - потому что поиск x.foo даст вам значение 23, а это int, не вызывается.

Еще один способ взглянуть на это -

class one(object):
  foo = lambda self: ...

class two(object):
  def foo(self): ...

class three(object):
  foo = 23

глубокой разницы нет - все они позволяют установить атрибут класса foo (один не вызывается, два - один, один связан с оператором def, два - с присваиваниями; различия - не глубоко с точки зрения поиска атрибутов в экземплярах этих классов).

Типичное использование для не подлежащих вызову атрибутов может быть:

class zap(zop):
  zep = None

  def blub(self):
    if self.zep is None: self.zep = 23
  ...&c...

Нет необходимости давать zap __init__ с self.zep = None и делегирование суперклассу __init__ (если есть) - проще просто наследовать zop '__init__ (если есть) и используйте атрибут класса настолько долго, насколько это возможно (вместо этого он станет атрибутом экземпляра тогда и только тогда, когда blub вызывается для этого экземпляра - также может сэкономить немного памяти для экземпляров, для которых blub никогда не вызывается; ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...