Переменные унаследованного базового класса Python

#python #class #oop #inheritance

#python #класс #ооп #наследование

Вопрос:

Итак, у меня есть Base класс с двумя дочерними классами. Идея заключалась в том, что у меня была бы модель, содержащая все данные, которые я мог бы подключить к одному из дочерних классов. Затем вызовите метод для установки заголовков для каждого из дочерних классов, а затем продублируйте данные из Model экземпляра Child класса. Однако я обнаружил, что после вызова add_header метода в первом экземпляре класса (в данном случае a) b также получил заголовок. Что меня немного смутило, потому что я думал, что инициированные классы не влияют друг на друга. Мой вопрос в том, почему это так, и можно ли этого избежать?

 class Base(object):
    __model__ = None
    headers = ['base_header','base_header2']

    def add_header(self, *args):
        for h in args:
            self.headers.append(h)

    def set_header_values(self):
        for h in self.headers:
            setattr(self, h, getattr(self.__model__, h))


class ChildOne(Base):
    def __init__(self, model):
        self.__model__ = model


class ChildTwo(Base):
    def __init__(self, model):
        self.__model__ = model


class Model(object):
    foo = 'bar'

m = Model()
a = ChildOne(m)
b = ChildTwo(m)
a.add_header('tralala')
print b.headers // Output ['base_header','base_header2','tralala']
  

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

1. Немного неясно, что вы пытаетесь сделать, почему headers в первую очередь не является переменной экземпляра?

2. Заголовки @timgeb содержат некоторый «базовый» заголовок, который присутствует в обеих моделях

Ответ №1:

«после вызова метода add_header для первого экземпляра класса (в данном случае a) b также получил заголовок», потому что оба экземпляра имеют одинаковые заголовки переменных. заголовки должны быть экземпляром, а не переменной класса

 class Base(object):
    __model__ = None
    def __init__(self):
        self.headers = []

    def add_header(self, *args):
        for h in args:
            self.headers.append(h)

    def set_header_values(self):
        for h in self.headers:
            setattr(self, h, getattr(self.__model__, h))


class ChildOne(Base):
    def __init__(self, model):
        super(ChildOne, self).__init__()
        self.__model__ = model


class ChildTwo(Base):
    def __init__(self, model):
        super(ChildTwo, self).__init__()
        self.__model__ = model


class Model(object):
    foo = 'bar'

m = Model()
a = ChildOne(m)
b = ChildTwo(m)
a.add_header('tralala')
print a.headers
print b.headers 
  

Вывод

[‘tralala’]

[]

Дополнительное примечание

Переменные класса и экземпляра Python вызывают путаницу. Рассмотрим следующий пример:

 class A:
    l =[] 

class B:
    l =[]

x = A()
y = A()
x.l.append(1)
print 'class A ', A.l, x.l, y.l

x = B()
y = B()
x.l = [1]
print 'class B ', B.l, x.l, y.l
  

Вывод

 class A  [1] [1] [1]
class B  [] [1] []
  

В обоих примерах используется очень похожий доступ к элементу данных ‘l’, однако первый пример изменяет уже существующую переменную класса, а второй пример создает новую переменную экземпляра.

В вашем примере, если бы у вас было назначение self.headers = [...] вместо self.append(...) вашего вывода, все было бы по-другому.

Кроме того, __model__ атрибут в вашем вопросе не имеет никакого отношения к проблеме.