Niels
Niels

Reputation: 1603

Python inherited base class variables

So I have Base class with two Child classes. The idea was that I would have a model containing all data which I could plug into one of the child classes. Then call a method to set the headers on each of the child classes and then duplicate the data from the Model to the Child class instance. However I found out that after calling the add_header method on the first class instance (a in this case) b also got the header. Which kinda confused me because I thought that initiated classes do not affect one another. My question is why is this the case and can it possibly be avoided?

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']

Upvotes: 2

Views: 3882

Answers (1)

dmitri
dmitri

Reputation: 3294

"after calling the add_header method on the first class instance (a in this case) b also got the header" Because both instances share same variable headers. headers should be instance rather than a class variable

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 

Output

['tralala']

[]

Additional note

Python class and instance variables cause confusions. Consider the following example:

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

Output

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

Both examples use very similar looking access to data member 'l' however first example modifies the already existing class variable while second example creates a new instance variable.

In your example should you had an assignment self.headers = [...] instead of self.append(...) your output would be different.

Beside, __model__ attribute in your question has nothing to do with the problem.

Upvotes: 3

Related Questions