Python:从派生类中获取基类值

时间:2011-02-08 16:29:55

标签: python oop

希望这很清楚:

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的项目设计项目管理解决方案,并且正在玩类和继承,以了解它们如何能够帮助我。

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

我习惯于以变量为前缀的变量。并且没有对使用没有自我的更“全局”变量的类进行过多尝试。 。如果我把一切都变得全球化,没有自我,我可以毫不费力地使用Project.fps,但是我的脖子上有一个“糟糕的编程习惯”警告。也许有更好,更整洁的方式?

修改

经过一番阅读,super()似乎有点危险,而且比我想象的要多一些。我主要有单继承类,甚至不确定如何使用钻石层次结构。是否有更安全的方法来访问超类变量和不包含super()的方法?

修改

好吧,看看这是否有意义,或者我是否认为这一切都是错误的。

我正在以群组和孩子的身份看待课程和继承。一个孩子知道它的父母及其所有的价值观。一个孩子对另一个父母知道父母的价值观。我想要完成的是将所有镜头都创建为项目的一部分。现在,我正在Project()类中创建Shot()实例,将实例添加到镜头列表中,然后在Project()实例中维护。

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总是一个空字符串。

2 个答案:

答案 0 :(得分:6)

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

另请注意

super

非常不同
class C(object):
    x = ...

前者创建一个类变量,由class C(object): def __init__(self): self.x = ... 的所有实例共享。后者创建一个实例变量,C的每个实例都有自己的实例。 (同样,全局变量不会绑定到实例 - 但我假设您正在讨论上述内容?)

答案 1 :(得分: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__,但缺点是您需要记住始终调用辅助构造函数在创建对象时,或者您的对象将部分未初始化。

更新(回答更新后的问题):

你似乎在这里混合了两个不相关的父母身份概念。继承是关于类型层次结构的,您似乎是在所有权层次结构之后(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()