Ответ 1
"Из приведенных выше кодов я думал, что, возможно, NewCounter1.count равно NewCounter1. _class_.count"
Проблема в том, что в момент этого предложения в вашем вопросе, после единственных инструкций:
NewCounter1 = counter()
NewCounter2 = counter()
NewCounter2.__class__.count = 3
создав NewCounter1 и NewCounter2
и изменив атрибут класса counter.count,
нет объектов NewCounter1.count и NewCounter2.count, а затем "equals" не имеет реального значения.
.
См. создание NewCounter1 и сразу после:
class counter:
count = 0
def __init__(self):
self.__class__.count += 1
print 'counter.count BEFORE ==',counter.count # The result is 0
NewCounter1 = counter()
print '\nNewCounter1.__dict__ ==',NewCounter1.__dict__ # The result is {}
print 'NewCounter1.count ==',NewCounter1.count # The result is 1
print 'counter.count AFTER ==',counter.count # The result is 1
NewCounter._dict _ - пространство имен экземпляра NewCounter1 print NewCounter1.count
печатает то же самое, что и print counter.count
Однако "count" (строка "count" ) не находится в пространстве имен NewCounter1, то есть в пространстве имен созданного объекта нет атрибута count пример!
Как это возможно?
Это потому, что экземпляр создается без присвоения идентификатора 'count' внутри _init _
- > нет реального создания какого-либо атрибута в качестве поля в NewCounter1, т.е. никакого создания атрибута INSTANCE.
Следствием этого является то, что когда инструкция
print 'NewCounter1.count ==',NewCounter1.count
, интерпретатор не находит атрибут экземпляра в пространстве имен NewCounter1, а затем переходит к классу экземпляра для поиска ключа "count" в этом пространстве имен этого класса; там он находит "count" как ключ атрибута CLASS и может принимать значение VALUE объекта counter.count как VALUE для отображения в ответ на инструкцию.
Экземпляр класса имеет пространство имен, реализованное как словарь, который первое место, в котором выполняется поиск ссылок атрибутов. Когда атрибут там не найден, а класс экземпляров имеет атрибут по этому имени, поиск продолжается с классом атрибутов. http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy
Итак, NewCounter1.count equals NewCounter1.__class__.count
здесь означает, что значение VALUE для NewCounter1.count, даже если это действительно не существует, является значением VALUE атрибута класса NewCounter1. class.count. Здесь "есть" - это английский глагол, а не языка, который проверяет идентичность двух объектов, а это означает, что "считается имеющим"
Когда NewCounter2.__class__.count = 3
выполняется, затрагивается только атрибут класса counter.count. Пространства имен NewCounter1 и NewCounter2 остаются пустыми и выполняется тот же механизм перехода к классу, чтобы найти значение counter.count.
.
В конце, когда выполняется NewCounter2.count = 5
, на этот раз атрибут INSTANCE count создается как поле в объекте NewCounter2, а "count" появляется в пространство имен NewCounter2.
Он ничего не перезаписывает, потому что в экземпляре не было ничего предшествующего __dict__
Никакие другие изменения не влияют на NewCounter1 и counter.count
Следующий код более явно показывает основные события во время выполнения:
from itertools import islice
class counter:
count = 0
def __init__(self):
print (' | counter.count first == %d at %d\n'
' | self.count first == %d at %d')\
% (counter.count,id(counter.count),
self.count,id(self.count))
self.__class__.count += 1 # <<=====
print (' | counter.count second == %d at %d\n'
' | self.count second == %d at %d\n'
' | id(counter) == %d id(self) == %d')\
% (counter.count,id(counter.count),
self.count,id(self.count),
id(counter),id(self))
def display(*li):
it = iter(li)
for ch in it:
nn = (len(ch)-len(ch.lstrip('\n')))*'\n'
x = it.next()
print '%s == %s %s' % (ch,x,'' if '__dict__' in ch else 'at '+str(id(x)))
display('counter.count AT START',counter.count)
print ('\n\n----- C1 = counter() ------------------------')
C1 = counter()
display('C1.__dict__',C1.__dict__,
'C1.count ',C1.count,
'\ncounter.count ',counter.count)
print ('\n\n----- C2 = counter() ------------------------')
C2 = counter()
print (' -------------------------------------------')
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
print '\n\n------- C2.__class__.count = 3 ------------------------\n'
C2.__class__.count = 3
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
print '\n\n------- C2.count = 5 ------------------------\n'
C2.count = 5
display('C1.__dict__',C1.__dict__,
'C2.__dict__',C2.__dict__,
'C1.count ',C1.count,
'C2.count ',C2.count,
'C1.__class__.count',C1.__class__.count,
'C2.__class__.count',C2.__class__.count,
'\ncounter.count ',counter.count)
результат
counter.count AT START == 0 at 10021628
----- C1 = counter() ------------------------
| counter.count first == 0 at 10021628
| self.count first == 0 at 10021628
| counter.count second == 1 at 10021616
| self.count second == 1 at 10021616
| id(counter) == 11211248 id(self) == 18735712
C1.__dict__ == {}
C1.count == 1 at 10021616
counter.count == 1 at 10021616
----- C2 = counter() ------------------------
| counter.count first == 1 at 10021616
| self.count first == 1 at 10021616
| counter.count second == 2 at 10021604
| self.count second == 2 at 10021604
| id(counter) == 11211248 id(self) == 18736032
-------------------------------------------
C1.__dict__ == {}
C2.__dict__ == {}
C1.count == 2 at 10021604
C2.count == 2 at 10021604
C1.__class__.count == 2 at 10021604
C2.__class__.count == 2 at 10021604
counter.count == 2 at 10021604
------- C2.__class__.count = 3 ------------------------
C1.__dict__ == {}
C2.__dict__ == {}
C1.count == 3 at 10021592
C2.count == 3 at 10021592
C1.__class__.count == 3 at 10021592
C2.__class__.count == 3 at 10021592
counter.count == 3 at 10021592
------- C2.count = 5 ------------------------
C1.__dict__ == {}
C2.__dict__ == {'count': 5}
C1.count == 3 at 10021592
C2.count == 5 at 10021568
C1.__class__.count == 3 at 10021592
C2.__class__.count == 3 at 10021592
counter.count == 3 at 10021592
.
Интересно, что нужно добавить инструкцию
self.count = counter.count
ПЕРЕД
self.__class__.count += 1 # <<=====
наблюдать за изменением результатов
.
В заключение, точка не касалась __class__
, а механизм поиска атрибута, и этот механизм вводит в заблуждение при игнорировании.