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

Mar*_*son 10 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()
Run Code Online (Sandbox Code Playgroud)

我希望单独设置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()
Run Code Online (Sandbox Code Playgroud)

我可以在这里看到逻辑中的错误步骤,但没有真正的解决方法..似乎每个孩子都以这种方式获取父实例,其中parent_id总是一个空字符串.

sha*_*ang 7

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()
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢在所有子类中重复使用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()
Run Code Online (Sandbox Code Playgroud)

在这种模式中,您不需要重复任何父项的参数,甚至不需要调用子项中的父项__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()
Run Code Online (Sandbox Code Playgroud)


小智 6

你只需要告诉你Child运行初始化myParent.之后,当前的instance(self)所有实例属性myParent都具有("是a")的实例,因此您可以使用self.parentNumber.您可以通过将这样做super(Child, self).__init__()Child.__init__(理想情况下,在第一行) - myParent.__init__(self)会的工作,但它可能是错的(以微妙的方式),当基类的变化或在多重继承的情况下.super如果您使用的是Python 3 ,则可以删除所有参数.

另请注意

class C(object):
    x = ...
Run Code Online (Sandbox Code Playgroud)

与...非常不同

class C(object):
    def __init__(self):
        self.x = ...
Run Code Online (Sandbox Code Playgroud)

前者创建一个类变量,由所有实例共享C.后者创建一个实例变量,每个实例C都有自己的实例.(同样,全局变量不绑定到实例 - 但我假设你在讨论上面的内容?)