python - 基本继承(在python中)

标签 python oop inheritance

用户,
我有一个关于继承的基本问题(在Python中)。我有两个类,其中一个继承自另一个类

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

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

是否有可能创建父对象和多个子对象,这些对象引用同一父对象?它应该是这样的,父对象包含多个变量,每当我从一个孩子那里访问相应的变量时,我实际上访问父变量。也就是说,如果我把它换成一个孩子,它也会改变所有其他的孩子,并且数据只在内存中存储一次(而不是为每个孩子复制)。
提前谢谢你。
这里有一个可能的解决办法,我认为不太好
class P:
    def __init__(self, name):
        self.pname = name

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

这真的是最先进的还是存在其他的概念?
塞巴斯蒂安
谢谢大家帮我,也用名字约定:)但我还是不太满意。也许我可以举一个更先进的例子来强调我真正想做的事情。
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

现在我可以做以下事情
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'

到目前为止这正是我想要的。每个子类都有一个不同的变量名,父类访问各个变量。正常遗传。
然后是来自父类和每个子类的变量数据。但是,现在以下操作不再有效
In [39]: c1.data = "tst"

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

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

我希望c1.data中的更改也会影响c2.data,因为我希望变量是共享的,某种程度上是这个父类的全局变量。
不止如此。我还想创建不同的p实例,每个实例都有自己的数据变量。当我创建一个新的c对象时,我想指定应该从哪个p对象数据导入,即shared…。
更新:
评论“YeQue:”谢谢,这正朝着我想要的方向发展。但是,现在__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类继承了PVP类的PVAR,所以我的天真的想法是,如果我创建了一个C的新实例,我应该能够指定哪个(现有的)P对象应该用作父对象,而不是当调用C.的P.__init__内的__init__内部时创建一个完全新的P对象。听起来很简单,也许我忘了什么…
更新:
所以我发现this discussion这几乎就是我的问题。
有什么建议吗?
更新:
方法.class .class类似乎不再存在了。
更新:
以下是其他链接:
link to discussion
在那里,它是通过复制来解决的。但我不想复制父类,因为我希望它只存在一次…
更新:
很抱歉昨天离开了讨论,我有点不舒服…谢谢你的帖子!我现在要把它们通读一遍。我想了想,这里有一个可能的解决办法
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)

这有点麻烦,我希望有一个更简单的方法来实现这一点。但它的特点是PVAR只在类P中提到,C类不知道PVAR,因为它应该根据我对继承的理解。然而,当我创建C的新实例时,我可以指定一个现有的P实例,该实例将存储在变量POBCUTE中。当变量pvar被访问时,实际上存储在这个变量中的p实例的pvar被访问…
输出由
3078326816
3078326816
3078326816
3074996544
3074996544
3074996544
3078326816
3074996544
156582944
156583040
156583200
156583232
156583296
156583360

我现在来读你最后的评论,
最好的,塞巴斯蒂安
更新:
我认为最优雅的方法是以下(这不起作用)
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

我认为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)

输出与上述相同
3077745184
3077745184
3077745184
3074414912
3074414912
3074414912
3077745184
3074414912
144028416
144028448
144028480
144028512
144028544
144028576

更新:即使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

它有输出
newpvar1
1
1
2
2
2
1
2

然而,我发布的第一个版本起了作用:
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

有了输出
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

有人知道为什么会这样吗?我可能不太理解python处理这个__dict__的内部方式。

最佳答案

它应该是这样的,父对象包含多个变量,每当我从一个孩子那里访问相应的变量时,我实际上访问父变量。也就是说,如果我把它换成一个孩子,它也会改变所有其他的孩子,并且数据只在内存中存储一次(而不是为每个孩子复制)。
那不是遗产。
这是一个完全不同的概念。
你的“共享变量”仅仅是可以改变的对象,并且在其他对象中有引用。没什么有趣的。
继承与此完全不同。

关于python - 基本继承(在python中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5104366/

相关文章:

matlab - 通过将方法的名称和输入传递给函数/方法来处理 Matlab 中未定义的方法

Python:从导入类调用方法

java - 在 Java 中如何只扩展函数而不是整个类?

java - 混合连接和单表继承以及查询所有对象

c# - 从父类ctor调用重写的方法

python - 向量化/对比数据框与分类变量

c++ - 计算大矩阵的零空间

python - 尽管年份如何计算月份圆差?

python - 当 Python 给你一个对象的内存位置时,那是做什么用的?

java - Java中的继承(设计模式)