Поведение, которое вы видите, именно то, что вы должны ожидать.Когда вы определяете класс
>>> class Foo(object): pass
...
, вы можете изменить этот класс - не его экземпляры, а сам класс - потому что класс - это просто еще один объект, хранящийся в переменной Foo,Так, например, вы можете получить и установить атрибуты класса:
>>> Foo.a = 1
>>> Foo.a
1
Другими словами, ключевое слово class
создает новый тип объекта и связывает указанное имя с этим объектом.
Теперь, если вы определите класс внутри другого класса (кстати, это странная вещь), что эквивалентно определению локальной переменной внутри тела класса.И вы знаете, что делает определение локальных переменных внутри тела класса: он устанавливает их как атрибуты класса.Другими словами, переменные, определенные локально, хранятся в объекте класса, а не в отдельных экземплярах.Таким образом,
>>> class Foo(object):
... class Bar(object): pass
...
определяет класс Foo
с одним атрибутом класса, Bar
, который сам по себе является классом.Здесь не существует подклассов - классы Foo
и Bar
полностью независимы.(Достигнутое вами поведение можно повторить следующим образом:
>>> class Foo(object):
... class Bar(object): pass
...
>>> class Foo(object): pass
...
>>> class Bar(object): pass
...
>>> Foo.Bar = Bar
.)
Так что вы всегда изменяете одну и ту же переменную !Конечно, вы измените значения, которые видите;вы изменили их сами!
Похоже, ваша проблема в том, что вы несколько запутались между атрибутами экземпляра и класса, которые совсем не одно и то же.
A Атрибут class - это переменная, которая определяется по всему классу.То есть любой экземпляр класса будет иметь одну и ту же переменную.Например, большинство методов являются атрибутами класса, так как вы хотите вызывать одни и те же методы для каждого экземпляра (обычно).Вы также можете использовать атрибуты класса для таких вещей, как глобальные счетчики (сколько раз вы создали экземпляр этого класса?) И другие свойства, которые должны совместно использоваться экземплярами.
Атрибут instance является переменнойсвойственный экземпляру класса.То есть каждый экземпляр имеет свою копию переменной с возможно различным содержанием.Здесь вы храните данные в классах - например, если у вас есть класс Page
, вы хотите, чтобы атрибут contents
хранился для каждого экземпляра, поскольку разные Page
s, конечно, будут нуждаться в разных contents
.
В вашем примере вы хотите, чтобы Child1.Subcls.a
и Child2.Subcls.a
были различными переменными.Естественно, они должны зависеть от экземпляра!
Это может быть немного прыжком, но вы пытаетесь реализовать интерфейсы в стиле Java в Python?Другими словами, пытаетесь ли вы указать, какие свойства и методы должен иметь класс , без фактического определения этих свойств?
Раньше это считалось чем-то непифоническим, что нужно делать, поскольку преобладающее согласие заключалось в том, что вы должны позволить классам делать все, что они хотят, и перехватывать исключения, возникающие, когда они не определяют необходимое свойство или метод.Тем не менее, недавно люди поняли, что интерфейсы на самом деле иногда полезны, и в Python были добавлены новые функциональные возможности, позволяющие это: абстрактные базовые классы .