用户,
我有一个关于继承(在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
这是否真的是最先进的技术,还是存在其他概念?
Sebastian
非常感谢大家帮助我,包括名称规范方面的帮助 :) 但我仍然不太满意。也许我可以举一个更高级的例子来强调我真正想做的事情。
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对象继承数据,即共享...
更新:
感谢@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继承pvar自类P,因此pvar为C所知。我的天真想法是,如果我创建一个新的C实例,我应该能够指定使用哪个(现有的)P对象作为父对象,并且不要像在C的__init__
中调用P.__init__
时那样创建一个全新的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)
这有点繁琐,希望有更简单的方法实现。但它具有一个特性,即只在类P中提到了pvar,而根据我的继承理解,类C不知道pvar的存在。然而,当我创建C的新实例时,可以指定一个现有的P实例,该实例将存储在变量pobject中。当访问变量pvar时,实际上是访问存储在该变量中的P实例的pvar...
输出如下:
3078326816
3078326816
3078326816
3074996544
3074996544
3074996544
3078326816
3074996544
156582944
156583040
156583200
156583232
156583296
156583360
我现在会阅读你最近的评论,祝一切顺利,Sebastian
更新:
我认为最优雅的方式是以下方式(但不起作用)
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的解释。但是,由于这只是一个hack,应该有一个官方版本的相同...
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__
的内部方式...