Python. Странное поведение атрибутов класса - PullRequest
1 голос
/ 25 апреля 2010
>>> class Abcd:

...     a = ''
...     menu = ['a', 'b', 'c']
... 
>>> a = Abcd()
>>> b = Abcd()
>>> a.a = 'a'
>>> b.a = 'b'
>>> a.a
'a'
>>> b.a
'b'

Это все правильно, и у каждого объекта есть свое «а», но ...

>>> a.menu.pop()
'c'
>>> a.menu
['a', 'b']
>>> b.menu
['a', 'b']

Как это могло случиться? А как использовать список в качестве атрибута класса?

Ответы [ 3 ]

7 голосов
/ 25 апреля 2010

Это связано с тем, что при инициализации свойства menu все экземпляры устанавливаются так, чтобы они указывали на один и тот же список, а не на разные списки с одинаковым значением.

Вместо этого используйте функцию-член __init__ класса для инициализации значений, создавая тем самым новый список и назначая этот список свойству для этого конкретного экземпляра класса:

class Abcd:
    def __init__(self):
        self.a = ''
        self.menu = ['a', 'b', 'c']
4 голосов
/ 25 апреля 2010

См. объекты класса в руководстве и обратите внимание на использование self.

Использовать атрибуты экземпляра, а не атрибуты класса (а также классы нового стиля):

>>> class Abcd(object):
...     def __init__(self):
...         self.a = ''
...         self.menu = ['a','b','c']
...         
>>> a=Abcd()
>>> b=Abcd()
>>> a.a='a'
>>> b.a='b'
>>> a.a
'a'
>>> b.a
'b'
>>> a.menu.pop()
'c'
>>> a.menu
['a', 'b']
>>> b.menu
['a', 'b', 'c']
>>> 
0 голосов
/ 25 апреля 2010

потому что переменные в Python - это просто "метки"

и Abcd.menu, и a.menu ссылаются на один и тот же объект списка.

в вашем случае вы должны присвоить метку новому объекту,

не изменять объект на месте.

Вы можете запустить

a.menu = a.menu[:-1]

вместо

a.menu.pop()

чтобы почувствовать разницу

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