Народ, может я чего-то недопонимаю и так оно и должно быть. Но это нормально, что переменные, объявленные в определении класса, инициализируются в момент определения класса, а не в момент создания экземпляра класса?
Понимаю, что сумбурно звучит, просто столкнулся тут с ситуацией. Есть базовый класс, в котором инициализируется экземпляр другого класса. И вдруг я обнаруживаю, что именно этот экземпляр является общим для всех экземпляров как самого базового класса, так и любых его наследников.
Вот пример, чтобы было проще понять, что я имею ввиду:
>>> class A(object):
... num = 1
...
>>> class B(object):
... a = A()
...
>>> class C(object):
... a = A()
...
>>> class D(B): <--- Наследник B
... pass
...
>>> a = A()
>>> b = B()
>>> c = C()
>>> d = D()
>>> a.num, b.a.num, c.a.num, d.a.num
(1, 1, 1, 1)
>>> a
<__main__.A object at 0x8ec5a8c>
>>> b.a
<__main__.A object at 0x8ec590c> <--- WTF??? o_О Адрес совпадает.
>>> c.a
<__main__.A object at 0x8ec59cc>
>>> d.a
<__main__.A object at 0x8ec590c> <--- WTF??? o_О Адрес совпадает.
>>> a.num, b.a.num, c.a.num, d.a.num
(1, 1, 1, 1)
>>> b.a.num = 666 <--- d.a.num не трогаем, обратите внимание
>>> a.num, b.a.num, c.a.num, d.a.num
(1, 666, 1, 666) <--- WTF??? o_О d.a.num изменился вместе с b.a.num.
То есть мне как-то казалось, что если я создал новый экземпляр класса D(), то и входящий в его состав экземпляр класса A() будет создан заново. Но вместо этого я наблюдаю, что этот самый экземпляр будучи раз созданным при определении класса B() просто переходит в свежесозданный экземпляр наследственного класса D(). Другими словами, ведут они себя примерно как статические поля в том же шарпе (про джаву не могу сказать, но там наверное также). А еще заметил, что конструктор вложенного класса вызывается в момент, когда я импортирую класс из модуля даже если я не создаю никаких экземпляров.
Вопрос. Что это за фигня или может так оно и было задумано, просто я дурак? Но в любом случае вопрос, что с этим делать и как добиться переинициализации всех полей при создании каждого нового экземпляра остается открытым. Объявлять все внутри __init__() пока что не хотелось бы.