2011-02-08 54 views
7

希望这是非常明显的:的Python:从派生类中获取基类值

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() 

我想单独设置parentNumber,进而达到通过该子类号,在这种情况下使用它的一些乘法。

我是OOP领域的新手,所以任何关于继承的一般指针都是受欢迎的!

更多信息: 我设计了基于VFX-项目的项目管理解决方案,并正在与类和继承玩,看看他们如何能帮助我最。

现在,我已经得到了顶级课程,项目和一个派生类,Shot。 Shot具有一个self.length变量和特定镜头的长度。它还有一个getLengthInSeconds()方法,它使用self.length和Project.fps来确定长度(以秒为单位)。 Project有一个setFps()方法,其中在创建类的实例之后设置fps。

我很习惯以self为前缀的变量。并没有用更多的“全局”变量在没有自我的情况下尝试过很多类。 。如果我把所有东西都做成全球化的东西,那么我就可以毫无麻烦地使用Project.fps,但是我在我的neckhair中收到了一个“糟糕的编程习惯”警告。也许有更好,更整洁的方式?

编辑:

一些阅读后,超()似乎有点危险,有点比我更需要我的想法。我主要有单继承类,甚至不知道如何使用钻石层次结构。是否有更安全的方式来访问超类变量和方法,不包括super()?

编辑:

还好吧,看看这是有道理的,或者如果我想这都是错误的。

我正在寻找类和继承作为组和孩子。一个孩子知道它是父母,所有的价值。一个孩子到另一个父母知道父母的价值观。我试图完成的是将所有镜头创建为项目的一部分。现在,我从Project()类中创建Shot()实例,将实例添加到项目()实例中保留的镜头列表中。

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() 

我有点看这里的逻辑错误的步骤,但它周围没有真正的方法.. 好像每个孩子得到父母的新实例这种方式,在parent_id始终是一个空字符串。

+0

你需要调用父类的构造。 – 2011-02-08 16:32:31

回答

5
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()

您通常可以管理不super就好了,当你不具备多重继承或其他边境情况,但如果基类发生更改,则需要记住将init(以及任何其他显式引用myParent的方法)的父类名更改。

如果您父母的__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

如果你不喜欢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() 

在这个模式中,你不需要重复任何父母的参数,甚至在孩子中调用父母的__init__,但缺点是在创建对象时需要始终调用辅助构造函数,否则对象将部分未初始化。

UPDATE(回答这个问题更新):

你似乎在这里混合父母的两个不相关的概念。继承是关于类型层次结构的,你似乎在所有权层次结构之后(is-a与has-a)。

我会组织你的更新代码:

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()
5

您只需告诉Child即可从myParent运行初始化。之后,当前实例(self已具有所有实例属性myParent将具有的实例("is a"),因此您可以使用self.parentNumber。通过将super(Child, self).__init__()纳入Child.__init__(理想情况下,在第一行)可以工作,但当基类发生更改或多重继承时,它可能是错误的(以微妙的方式)。如果您使用的是Python 3,则可以将所有参数删除到super

还要注意的是

class C(object): 
    x = ... 

class C(object): 
    def __init__(self): 
     self.x = ... 

前者截然不同创建一个类变量,这是由C所有实例共享。后者创建一个实例变量,每个实例都有自己的实例。 (同样,全局变量不绑定到实例 - 但我认为你在谈论以上?)

+1

+1 ..它应该是`multiplyNumbers`中的`self.parentNumber`。 – sdolan 2011-02-08 16:36:57

+0

@sdolan:是的,包括在内。 – delnan 2011-02-08 16:41:44