Обновление атрибута dict из расширенного класса обновляет базовый класс.Зачем? - PullRequest
1 голос
/ 06 марта 2012
>>> class Test(object):
...   test = {}
... 
>>> class Test2(Test):
...   pass
... 
>>> Test2.test.update({1:2})
>>> Test.test
{1: 2}
>>> 

Я ожидал {}.Бывает и с классами старого стиля.

Ответы [ 5 ]

2 голосов
/ 06 марта 2012

Вам нужно использовать 2 подчеркивания, чтобы активировать класс / атрибут munging

>>> class Test(object):
...     __test = {}
...
>>> class Test2(Test):
...     pass
...
>>> Test2.__test.update({1:2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Test2' has no attribute '__test'

Из-за атрибута munging атрибут можно найти по адресу Test2._Test__test вместо

Если вы хотите, чтобы все подклассы автоматически получали свой собственный атрибут __test, вы можете использовать метакласс для Test

1 голос
/ 06 марта 2012

Нет ничего странного в том, как работает update. Дело в том, что test является атрибутом класса , а атрибуты класса являются общими для всех классов (пока кто-то не связывает test с чем-то другим).

Посмотрите на эту сессию IDE:

>>> class Test(object):
...     test = {}
... 
>>> class Test2(Test):
...     pass
... 
>>> id(Test.test)
32424144
>>> id(Test2.test)
32424144
>>> Test.test.update({1:2})
>>> Test2.test
{1: 2}
>>> Test2.test = {}
>>> id(Test2.test)
32424480
>>> Test.test
{1: 2}
>>> Test2.test
{}
>>> del Test2.test
>>> Test2.test
{1: 2}

Для получения дополнительной информации о том, как работают атрибуты класса, смотрите Ссылка на модель данных в разделе Классы.

0 голосов
/ 06 марта 2012

Потому что это один и тот же объект. Точнее, Test2.test - это способ доступа к тому же, что и Test.test, потому что, когда он не найден локально, он ищется в суперклассе.

Я не понимаю, почему вы ожидаете чего-то другого. (Это не работает так, как вы ожидаете, на любых других языках, которые я могу себе представить.)

0 голосов
/ 06 марта 2012

Это вопрос ссылок.Возьмем для примера:

>>> class Test(object):
...   val = 1
... 
>>> class Test2(Test):
...   pass
... 
>>> Test2.val = 2
>>> Test.val
1

Здесь для подкласса val переназначается 2. 2. 1004 *

Для списков и словарей оба ссылаются на один и тот же объект, и любое обновление / добавление будет видно в суперклассе.Если вы, однако, переназначаете:

>>> class Test(object):
...   test = {}
... 
>>> class Test2(Test):
...   pass
... 
>>> Test2.test = {1:2}
>>> Test.test
{}
0 голосов
/ 06 марта 2012
Test2.test.update({1:2})

Обновляет атрибут Test базового класса, унаследованный Test2.

Если вы хотите, чтобы у каждого из них был свой диктат, выполните:

>>> class Test(object):
...     test = {}
... 
>>> class Test2(Test):
...     test = {}
... 
>>> Test2.test.update({1:2})
>>> Test.test
{}
>>> 

В Python есть функция, которая мне очень нравится: наследование данных, которое вы только что видели в действии.

...