Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

basic inheritance (in python)

users,

I have a basic question concerning inheritance (in python). I have two classes and one of them is inherited from the other like

class   p:
    def __init__(self,name):
        self.pname  = name

class   c(p):
    def __init__(self,name):
        self.cname  = name

Is there any possibility that I can create a parent object and several child objects which refer to the SAME parent object? It should work like that that the parent object contains several variables and whenever I access the corresponding variables from a child I actually access the variable form the parent. I.e. if I change it for one child it is changed also for all other childes and the data are only stored once in memory (and not copied for each child...)

Thank you in advance.

Here is a possible workaround which I do not consider as so nice

class P:
    def __init__(self, name):
        self.pname = name

class C:
    def __init__(self, name,pobject):
        self.pobject = pobject
        self.cname = name

Is this really the state of the art or do there exist other concepts?

Sebastian

Thank you all for helping me, also with the name conventions :) But I am still not very satisfied. Maybe I give a more advanced example to stress what I really want to do.

class P:
    data = "shareddata"
    def __init__(self,newdata):
        self.data = newdata 

    def printname(self):
        print self.name 

class C(P):
    def __init__(self,name):
        self.name = name

Now I can do the following

In [33]: c1 = test.C("name1")

In [34]: c2 = test.C("name2")

In [35]: c1.printname()
name1

In [36]: c2.printname()
name2

In [37]: c1.data
Out[37]: 'shareddata'

In [38]: c2.data
Out[38]: 'shareddata'

And this is so far exactly what I want. There is a variable name which is different for every child and the parent class accesses the individual variables. Normal inheritance. Then there is the variable data which comes from the parent class and every child access it. However, now the following does not work any more

In [39]: c1.data = "tst"

In [40]: c2.data
Out[40]: 'shareddata'

In [41]: c1.data
Out[41]: 'tst'

I want the change in c1.data to affect also c2.data since I want the variable to be shared, somehow a global variable of this parent class.

And more than that. I also want to create different instances of P, each having its own data variable. And when I create a new C object I want to specify from which P object data should be inhetited i.e. shared....

UPDATE:

remark to the comment of @eyquem: Thanks for this, it is going into the direction I want. However, now the __class__.pvar is shared among all objects of the class. What I want is that several instances of P may have a different pvar. Lets assume P1 has pvar=1 and P2 has pvar=2. Then I want to create children C1a, C1b, C1c which are related to P1, i.e. if I say C1a.pvar it should acess pvar from P1. Then I create C2a, C2b, C2c and if I access i.e. C2b.pvar I want to access pvar from P2. Since the class C inherits pvar from the class P pvar is known to C. My naive idea is that if I create a new instance of C I should be able to specify which (existing) P object should be used as the parent object and not to create a completely new P object as it is done when calling P.__init__ inside of the __init__ of C... It sounds simple to me, maybe I forget something...

UPDATE:

So I found this discussion which is pretty much my question

Any suggestions?

UPDATE:

The method .class._subclasses_ seems to be not existing any more..

UPDATE:

Here is onother link:

link to discussion

There it is solved by copying. But I do not want to copy the parent class since I would like that it exists only once...

UPDATE:

Sorry for leaving the discussion yesterday, I am a bit ill... And thank you for the posts! I will now read through them. I thought about it a bit more and here is a possible solution I found

class P(object):
    def __init__(self,pvar):
        self.pobject    = None
        self._pvar  = pvar

    @property
    def pvar(self):
    if self.pobject != None:
        return  self.pobject.pvar
    else:
            return self._pvar
    @pvar.setter
    def pvar(self,val):
    if self.pobject != None:
        self.pobject.pvar = val
    else:
            self._pvar=val

    def printname(self):
    print self.name


class C(P):
    def __init__(self,name,pobject):  #<-- The same default `P()` is 
                                          # used for all instances of `C`, 
                                          # unless pobject is explicitly defined.
    P.__init__(self,None)
        self.name   = name
        self.pobject = pobject


p1  = P("1")
p2  = P("2")


c1a = C("c1a",p1)
c1b = C("c1b",p1)
c1c = C("c1c",p1)
c2a = C("c2a",p2)
c2b = C("c2b",p2)
c2c = C("c2c",p2)


print   id(c1a.pvar)
print   id(c1b.pvar)
print   id(c1c.pvar)
print   id(c2a.pvar)
print   id(c2b.pvar)
print   id(c2c.pvar)
print   id(p1.pvar)
print   id(p2.pvar)

print   id(c1a.name)
print   id(c1b.name)
print   id(c1c.name)
print   id(c2a.name)
print   id(c2b.name)
print   id(c2c.name)

It is a bit cumbersome and I hope that there is a simpler way to achieve this. But it has the feature that pvar is only mentioned in the class P and the class C does not know about pvar as it should be according to my understanding of inheritance. Nevertheless when I create a new instance of C I can specify an existing instance of P which will be stored in the variable pobject. When the variable pvar is accessed actually pvar of the P-instance stored in this variable is accessed...

The output is given by

3078326816
3078326816
3078326816
3074996544
3074996544
3074996544
3078326816
3074996544
156582944
156583040
156583200
156583232
156583296
156583360

I will read now through your last comments,

all the best, Sebastian

UPDATE:

I think the most elegant way would be the following (which DOES NOT work)

class P(object):
    def __init__(self,pvar):
        self.pvar   = pvar

    def printname(self):
        print self.name


class C(P):
    def __init__(self,name,pobject):  
        P = pobject
        self.name   = name

I think python should allow for this...

UPDATE:

Ok, now I found a way to achieve this, due to the explanations by eyquem. But Since this is really a hack there should be an official version for the same...

def replaceinstance(parent,child):
    for item in parent.__dict__.items():
        child.__dict__.__setitem__(item[0],item[1])
        print item

class P(object):
    def __init__(self,pvar):
        self.pvar   = pvar

    def printname(self):
    print self.name


class C(P):
    def __init__(self,name,pobject):
    P.__init__(self,None)
    replaceinstance(pobject,self)
        self.name   = name



p1  = P("1")
p2  = P("2")


c1a = C("c1a",p1)
c1b = C("c1b",p1)
c1c = C("c1c",p1)
c2a = C("c2a",p2)
c2b = C("c2b",p2)
c2c = C("c2c",p2)


print   id(c1a.pvar)
print   id(c1b.pvar)
print   id(c1c.pvar)
print   id(c2a.pvar)
print   id(c2b.pvar)
print   id(c2c.pvar)
print   id(p1.pvar)
print   id(p2.pvar)

print   id(c1a.name)
print   id(c1b.name)
print   id(c1c.name)
print   id(c2a.name)
print   id(c2b.name)
print   id(c2c.name)

the output is the same as above

3077745184
3077745184
3077745184
3074414912
3074414912
3074414912
3077745184
3074414912
144028416
144028448
144028480
144028512
144028544
144028576

UPDATE: Even if the id's seem to be right, the last code does not work as is clear from this test

c1a.pvar    = "newpvar1"

print   c1a.pvar
print   c1b.pvar
print   c1c.pvar
print   c2a.pvar
print   c2b.pvar
print   c2c.pvar
print   p1.pvar
print   p2.pvar

it has the output

newpvar1
1
1
2
2
2
1
2

However the version I posted first works:

class P(object):
    def __init__(self,pvar):
        self.pobject    = None
        self._pvar  = pvar

    @property
    def pvar(self):
    if self.pobject != None:
        return  self.pobject.pvar
    else:
            return self._pvar
    @pvar.setter
    def pvar(self,val):
    if self.pobject != None:
        self.pobject.pvar = val
    else:
            self._pvar=val

    def printname(self):
    print self.name


class C(P):
    def __init__(self,name,pobject):  #<-- The same default `P()` is 
                                          # used for all instances of `C`, 
                                          # unless pobject is explicitly defined.
    P.__init__(self,None)
        self.name   = name
        self.pobject = pobject


p1  = P("1")
p2  = P("2")


c1a = C("c1a",p1)
c1b = C("c1b",p1)
c1c = C("c1c",p1)
c2a = C("c2a",p2)
c2b = C("c2b",p2)
c2c = C("c2c",p2)


print   id(c1a.pvar)
print   id(c1b.pvar)
print   id(c1c.pvar)
print   id(c2a.pvar)
print   id(c2b.pvar)
print   id(c2c.pvar)
print   id(p1.pvar)
print   id(p2.pvar)

print   id(c1a.name)
print   id(c1b.name)
print   id(c1c.name)
print   id(c2a.name)
print   id(c2b.name)
print   id(c2c.name)




print   "testing\n"

c1a.printname()
c1b.printname()
c1c.printname()
c2a.printname()
c2b.printname()
c2c.printname()


print   "\n"
c1a.name = "c1anewname"
c2b.name = "c2bnewname"


c1a.printname()
c1b.printname()
c1c.printname()
c2a.printname()
c2b.printname()
c2c.printname()


print "pvar\n"

print   c1a.pvar
print   c1b.pvar
print   c1c.pvar
print   c2a.pvar
print   c2b.pvar
print   c2c.pvar
print   p1.pvar
print   p2.pvar

print "\n"
c1a.pvar    = "newpvar1"

print   c1a.pvar
print   c1b.pvar
print   c1c.pvar
print   c2a.pvar
print   c2b.pvar
print   c2c.pvar
print   p1.pvar
print   p2.pvar

print "\n"
c2c.pvar    = "newpvar2"

print   c1a.pvar
print   c1b.pvar
print   c1c.pvar
print   c2a.pvar
print   c2b.pvar
print   c2c.pvar
print   p1.pvar
print   p2.pvar

with the output

3077745184
3077745184
3077745184
3074414912
3074414912
3074414912
3077745184
3074414912
144028416
144028448
144028480
144028512
144028544
144028576
testing

c1a
c1b
c1c
c2a
c2b
c2c


c1anewname
c1b
c1c
c2a
c2bnewname
c2c
pvar

1
1
1
2
2
2
1
2


newpvar1
newpvar1
newpvar1
2
2
2
newpvar1
2


newpvar1
newpvar1
newpvar1
newpvar2
newpvar2
newpvar2
newpvar1
newpvar2

Does anybody know why it is like that? I probably do not understand the internal way python works with this __dict__ so well...

like image 417
r6d9 Avatar asked May 23 '26 18:05

r6d9


1 Answers

It should work like that that the parent object contains several variables and whenever I access the corresponding variables from a child I actually access the variable form the parent. I.e. if I change it for one child it is changed also for all other childes and the data are only stored once in memory (and not copied for each child...)

That's not inheritance.

That's a completely different concept.

Your "shared variables" are simply objects that can be mutated and have references in other objects. Nothing interesting.

Inheritance is completely different from this.

like image 198
S.Lott Avatar answered May 25 '26 08:05

S.Lott



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!