Python:从派生类获取基类值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4935587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: Getting baseclass values from derived class
提问by Marcus Ottosson
Hope this is clear enough:
希望这足够清楚:
class myParent():
def __init__( self ):
self.parentNumber = 5
class Child( myParent ):
def __init__( self ):
self.childNumber = 4
def multiplyNumbers( self ):
print myParent.parentNumber * self.childNumber
p = Child()
p.multiplyNumbers()
I wish to set the parentNumber individually, and then reach that number via the child class, and in this case use it for some multiplication.
我希望单独设置 parentNumber,然后通过子类达到该数字,在这种情况下将其用于一些乘法。
I'm new to the OOP area so any general pointers on inheritance is welcome as well!
我是 OOP 领域的新手,因此也欢迎任何有关继承的一般指针!
More info:I'm designing a project management solution for vfx-based projects, and am playing with classes and inheritance to see how they can help me the most.
更多信息:我正在为基于 vfx 的项目设计一个项目管理解决方案,并且正在使用类和继承来了解它们如何最大程度地帮助我。
Right now, I've got the top class, Project, and a derived class, Shot. Shot has a self.length variable with the length of the specific shot. It's also got a getLengthInSeconds() method that uses self.length along with the Project.fps to determine the length in seconds. Project has a setFps() method in which the fps is set after an instance of the class is created.
现在,我有顶级类 Project 和派生类 Shot。Shot 有一个 self.length 变量,用于指定特定镜头的长度。它还有一个 getLengthInSeconds() 方法,它使用 self.length 和 Project.fps 来确定以秒为单位的长度。项目有一个 setFps() 方法,在该方法中,在创建类的实例后设置 fps。
I'm kind of used to variables being prefixed with self. and have not experimented much with classes using the more "global" variables without self. . If I make everything global, no self., I can use Project.fps without hassle, but I'm getting a "bad programming practice" warning in my neckhair. Perhaps there is a better, more neat, way?
我有点习惯以 self 为前缀的变量。并且没有对使用更“全局”的变量而不是 self 的类进行太多实验。. 如果我让一切都成为全球性的,没有自我,我可以毫不费力地使用 Project.fps,但我的脖子上收到了“糟糕的编程实践”警告。也许有更好、更整洁的方法?
Edit:
编辑:
After some reading, super() seems kinda dangerous, and a bit more than I need I think. I am mainly having single-inheritance classes and aren't even sure how to make use of diamond hierarchies.. Is there a safer way to access superclass variables and methods that doesn't include super()?
经过一些阅读, super() 似乎有点危险,而且比我认为的要多一些。我主要有单继承类,甚至不确定如何使用菱形层次结构.. 有没有更安全的方法来访问不包含 super() 的超类变量和方法?
Edit:
编辑:
Allright, see if this makes sense or if I'm thinking about it all wrong.
好吧,看看这是否有意义,或者我是否认为这一切都错了。
I'm looking at classes and inheritance as groups and children. A child knows it's parent and all it's values. A child to another parent knows That parents values. What I'm trying to accomplish is having all shots created be part of a project. And right now, I'm creating Shot() instances from within Project() class, adding the instances to a list of shots which is then maintained within the Project() instance.
我正在将类和继承视为组和子项。一个孩子知道它是父母以及它的所有价值观。另一个父母的孩子知道父母的价值观。我想要完成的是让所有创建的镜头成为项目的一部分。现在,我正在从 Project() 类中创建 Shot() 实例,将这些实例添加到一个镜头列表中,然后在 Project() 实例中进行维护。
i.e.
IE
class myParent( object ):
def __init__( self ):
self.parent_id = ''
self.children = []
def createChild( self, name ):
self.children.append( myChild( name ) )
def getChildren( self ):
return self.children
def setParentId( self, id ):
self.parentId = id
class myChild( myParent ):
def __init__( self, id ):
super(myChild, self).__init__()
self.id = id
def getParentId( self ):
return self.parent_id
p = myParent()
p.setParentId( 'parent01' )
p.createChild( 'child01' )
print p.getChildren()[0].getParentId()
I can sort of see the mis-steps in logic here, but no real way around it.. Seems like every child is getting a new instance of the parent this way, where parent_id is always an empty string.
我可以在这里看到逻辑中的错误步骤,但没有真正的解决方法。似乎每个孩子都以这种方式获得了父级的新实例,其中 parent_id 始终是一个空字符串。
采纳答案by shang
class myParent( object ):
def __init__( self ):
self.parentNumber = 5
class Child( myParent ):
def __init__( self ):
myParent.__init__( self )
self.childNumber = 4
def multiplyNumbers( self ):
print self.parentNumber * self.childNumber
p = Child()
p.multiplyNumbers()
You can usually manage just fine without superwhen you don't have multiple inheritance or other border cases, although if the base class changes, you will need to remember to change the parent class name from init(and any other method that refers to myParent explicitly).
super当您没有多重继承或其他边界情况时,您通常可以很好地管理,尽管如果基类发生变化,您将需要记住从init更改父类名称(以及任何其他显式引用 myParent 的方法) )。
If your parent's __init__ takes parameters, you need to pass them on from the child's __init__.
如果你的父母__init__ 接受参数,你需要从孩子的__init__.
class myParent( object ):
def __init__( self, customParam ):
self.parentNumber = 5
self.customParam = customParam
class Child( myParent ):
def __init__( self, customParam ):
myParent.__init__( self, customParam )
self.childNumber = 4
If you dislike the repetition of customParam in all child classes, there's an alternative OO pattern called two phase construction, which works like this:
如果您不喜欢在所有子类中重复 customParam,则有一种替代的 OO 模式称为两阶段构造,其工作方式如下:
class myParent( object ):
def customInit( self, customParam ):
self.parentNumber = 5
self.customParam = customParam
class Child( myParent ):
def __init__( self, customParam ):
self.childNumber = 4
p = Child()
p.customInit(10)
p.multiplyNumbers()
In this pattern, you don't need to repeat any of the parent's parameters, or even call the parent's __init__in the child, but the downside is that you will need to remember to always call the secondary constructor when creating objects, or your object will be left partially uninitialized.
在这种模式中,您不需要重复父的任何参数,甚至__init__不需要在子中调用父的参数,但缺点是您需要记住在创建对象时始终调用辅助构造函数,否则您的对象将部分未初始化。
UPDATE (to answer the updated question):
更新(回答更新的问题):
You seem to be mixing two unrelated concepts of parenthood here. Inheritance is about type hierarchy, and you seem to be after an ownership hierarchy (is-a versus has-a).
您似乎在这里混合了两个不相关的父母身份概念。继承是关于类型层次结构的,您似乎在追求所有权层次结构(is-a 与 has-a)。
I would structure your updated code like this:
我会像这样构建您更新的代码:
class myParent( object ):
def __init__( self, parentId ):
self.id = parentId
self.children = []
def createChild( self, name ):
self.children.append( myChild( name, self ) )
def getChildren( self ):
return self.children
class myChild( object ):
def __init__( self, childId, parent ):
self.id = childId
self.parent = parent
def getParentId( self ):
return self.parent.id
p = myParent( 'parent01' )
p.createChild( 'child01' )
print p.getChildren()[0].getParentId()
回答by Marcus Ottosson
You just need to tell Childto run the initialization from myParent. After that, the current instance (self) hasall the instance attributes an instance of myParentwould have ("is a"), so you can use self.parentNumber. You do so by putting super(Child, self).__init__()into Child.__init__(ideally, on the very first line) - myParent.__init__(self)would work, but it can be wrong (in subtle way) when the base class changes or in case of multiple inheritance. You can drop all the arguments to superif you're using Python 3.
您只需要告诉Child从myParent. 之后,当前实例 ( self)具有实例将具有的所有实例属性myParent( "is a"),因此您可以使用self.parentNumber. 您可以通过将这样做super(Child, self).__init__()进Child.__init__(理想情况下,在第一行) -myParent.__init__(self)会的工作,但它可能是错的(以微妙的方式),当基类的变化或在多重继承的情况下。super如果您使用的是 Python 3 ,则可以删除所有参数。
Also note that
还要注意的是
class C(object):
x = ...
is very different from
与
class C(object):
def __init__(self):
self.x = ...
The former creates a class variable, which is shared by all instances of C. The latter create an instance variable, each instance of Chas it's own. (Likewise, global variables aren't bound to instances - but I assume you were talking about the above?)
前者创建一个类变量,由 的所有实例共享C。后者创建一个实例变量,每个实例C都有它自己的。(同样,全局变量不绑定到实例 - 但我假设你在谈论上面的内容?)

