As you have noted, if you define lst
as a class attribute in Sub1
, it is shared among all instances, which is not what you want. So you have to define lst
as an instance attribute in Sub1
but then it has to be managed by an instance of Sub1
and not an instance of Sub2
. Here is a modified code that offers what you expect:
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
def add(self, item):
self.lst.append(item.name)
class Sub2(Sub1):
def __init__(self, name):
super().__init__()
self.name = name
m = Master()
m.foo = Sub1()
m.foo.add(Sub2('something'))
m.bla = Sub1()
m.bla.add(Sub2('else'))
print(m.foo.lst)
print(m.bla.lst)
Here is the ouput:
['something'] <-- m.foo.lst
['else'] <-- m.bla.lst
Rem1: When using super()
the whole class hierarchy has to be collaborative (i.e. use super()
in the constructor).
Rem2: In Python3, super()
is equivalent to super(classname, self)
Rem3: Don't use list
as a variable name (it is a builtin type)
Rem4: My code stores only the name
attribute in the list to mimic the example your gave, but I guess that in real life you would rather store instances of Sub2
in that list. To do so, simply remove the .name
in the add
function.
EDIT : Thinking a bit more about my answer, I came to another solution that may be closer to your initial attempt. Let me know which one works best for your actual problem...
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
class Sub2(Sub1):
def __init__(self, parent, name):
super().__init__()
parent.lst.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2(m.foo, 'something')
m.bla = Sub1()
m.bla.blub = Sub2(m.bla, 'else')
print(m.foo.lst)
print(m.bla.lst)