Когда я использую один базовый класс для двух разных классов и изменяю переменную в одном экземпляре класса, переменная в другом классе также изменяется?

#python #class #object #inheritance #constructor

Вопрос:

Приведенный ниже исходный код вызовет исключение в последней строке. Почему возникает исключение, если это два разных объекта?

 class BaseClass(object):
    
    accounts = dict()
    
    def AddAccount(self, account_id, account_var):
        if account_id in self.accounts.keys():
            raise Exception('Account already exists')
            
        self.accounts.update({account_id: account_var})
        
class Class1(BaseClass):
    pass

class Class2(BaseClass):
    pass

ACCOUNT_ID = '123'
c1 = Class1()
c2 = Class2()

c1.AddAccount(ACCOUNT_ID, 'abc')
c2.AddAccount(ACCOUNT_ID, 'abc')
 

Я пытался вызвать конструктор внутри каждого класса, но это не решает проблему. Мне это нравилось в каждом классе:

 def __init__(self):
    super().__init__()
 

Похоже BaseClass , что это всегда статический объект. Когда я изменюсь в одном объекте, он изменится в другом.

Комментарии:

1. «всегда статичный объект. Когда я изменюсь в одном объекте, он изменится в другом». да, в этом смысл атрибутов класса

2. В отличие от других языков, классы Python определяют только атрибуты классов, но никогда атрибуты экземпляров. Атрибуты экземпляра всегда создаются путем прямой модификации экземпляров, хотя обычно это делается с помощью методов экземпляра.

Ответ №1:

Вы определили accounts как переменную класса, а не переменную экземпляра. Вместо этого вы должны определить accounts в __init__ методе своего базового класса, чтобы он создавался с другой ссылкой для каждого экземпляра создаваемого вами класса.

 class BaseClass(object):
    def __init__(self):
        self.accounts = dict()
    
    def AddAccount(self, account_id, account_var):
        if account_id in self.accounts.keys():
            raise Exception('Account already exists')
            
        self.accounts.update({account_id: account_var})
 

Ответ №2:

Вы определили переменную класса в теле своего BaseClass .

Даже если вы ссылаетесь на него, self.accounts это не переменная экземпляра.

Например, если вам нужна переменная экземпляра, вам следует инициализировать ее с __init__() помощью self.accounts = {}