基本继承(在python中)

r6d*_*6d9 3 python oop inheritance

用户,

我有一个关于继承的基本问题(在python中).我有两个类,其中一个继承自另一个类

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

class   c(p):
    def __init__(self,name):
        self.cname  = name
Run Code Online (Sandbox Code Playgroud)

有没有可能我可以创建一个父对象和几个引用SAME父对象的子对象?它应该像父对象包含几个变量那样工作,每当我从子进入相应的变量时,我实际上从父进程访问变量.即如果我为一个孩子更改它,它也会更改为所有其他childes并且数据仅在内存中存储一​​次(并且不会为每个孩子复制...)

先感谢您.

这是一个可能的解决方法,我不认为这么好

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

class C:
    def __init__(self, name,pobject):
        self.pobject = pobject
        self.cname = name
Run Code Online (Sandbox Code Playgroud)

这真的是最先进的还是存在其他概念?

塞巴斯蒂安

谢谢大家帮助我,还有名称约定:)但我仍然不是很满意.也许我会举一个更高级的例子来强调我真正想做的事情.

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
Run Code Online (Sandbox Code Playgroud)

现在我可以做到以下几点

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'
Run Code Online (Sandbox Code Playgroud)

到目前为止,这正是我想要的.每个子节点都有一个不同的变量名,父类访问各个变量.正常继承.然后是来自父类的可变数据,每个子进程都访问它.但是,现在以下内容不再起作用

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

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

In [41]: c1.data
Out[41]: 'tst'
Run Code Online (Sandbox Code Playgroud)

我希望c1.data中的更改也影响c2.data,因为我希望共享变量,不知何故是这个父类的全局变量.

还有更多.我还想创建P的不同实例,每个实例都有自己的数据变量.当我创建一个新的C对象时,我想指定哪个P对象数据应该是athetited,即共享....

更新:

评论@eyquem的评论:谢谢你,它正朝着我想要的方向前进.但是,现在__class__.pvar在类的所有对象之间共享.我想要的是P的几个实例可能有不同的pvar.让我们假设P1有pvar = 1而P2有pvar = 2.然后我想创建与P1相关的子C1a,C1b,C1c,即如果我说C1a.pvar它应该从P1获得pvar.然后我创建了C2a,C2b,C2c,如果我访问即C2b.pvar,我想从P2访问pvar.由于C类从P类继承pvar,因此C的已知.我天真的想法是,如果我创建CI的新实例应该能够指定哪个(现有的)P对象应该用作父对象而不是P.__init____init__C语言内部调用时创建一个全新的P对象......对我来说听起来很简单,也许我忘记了......

更新:

所以我发现这个讨论几乎是我的问题

有什么建议?

更新:

方法 .class ._ subclasses _似乎不再存在..

更新:

这是另一个链接:

链接到讨论

它通过复制解决.但我不想复制父类,因为我希望它只存在一次......

更新:

很抱歉昨天离开讨论,我有点不舒服......谢谢你的帖子!我现在将通读它们.我考虑了一下,这是我找到的可能的解决方案

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)
Run Code Online (Sandbox Code Playgroud)

这有点麻烦,我希望有一种更简单的方法来实现这一点.但它的特点是pvar只在P类中提到,C类不知道pvar,因为它应该根据我对继承的理解.然而,当我创建CI的新实例时,可以指定将存储在变量pobject中的现有P实例.当访问变量pvar时,实际访问存储在该变量中的P实例的pvar ...

输出由.给出

3078326816
3078326816
3078326816
3074996544
3074996544
3074996544
3078326816
3074996544
156582944
156583040
156583200
156583232
156583296
156583360
Run Code Online (Sandbox Code Playgroud)

我现在将通过你的上一篇评论阅读,

一切顺利,塞巴斯蒂安

更新:

我认为最优雅的方式是以下(不起作用)

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
Run Code Online (Sandbox Code Playgroud)

我认为python应该允许这个......

更新:

好的,由于eyquem的解释,现在我找到了实现这一目标的方法.但由于这真的是一个黑客应该有一个相同的官方版本...

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)
Run Code Online (Sandbox Code Playgroud)

输出与上面相同

3077745184
3077745184
3077745184
3074414912
3074414912
3074414912
3077745184
3074414912
144028416
144028448
144028480
144028512
144028544
144028576
Run Code Online (Sandbox Code Playgroud)

更新:即使id似乎是正确的,最后的代码也不能正常工作,因为这个测试很明显

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
Run Code Online (Sandbox Code Playgroud)

它有输出

newpvar1
1
1
2
2
2
1
2
Run Code Online (Sandbox Code Playgroud)

然而,我发布的版本首先工作:

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
Run Code Online (Sandbox Code Playgroud)

与输出

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
Run Code Online (Sandbox Code Playgroud)

有人知道为什么会这样吗?我可能不明白python的内部方式__dict__如此好用......

S.L*_*ott 5

它应该像父对象包含几个变量那样工作,每当我从子进入相应的变量时,我实际上从父进程访问变量.即如果我为一个孩子更改它,它也会更改为所有其他childes并且数据仅在内存中存储一​​次(并且不会为每个孩子复制...)

那不是继承.

这是一个完全不同的概念.

您的"共享变量"只是可以变异的对象,并且在其他对象中具有引用.没什么有趣的.

继承与此完全不同.