3

我不理解以下 Python 代码中的“Self”对象:

>>> class Ancestor( object ):
    def __init__( self ):
        self.name = "Ancestor"
    def getName( self ):
        return self.name


>>> class Base1( Ancestor ):
    def __init__( self ):
        self.name = "Base1"
        super( Base1, self ).__init__( )
    def getName( self ):
        return self.name


>>> class Base2( Base1 ):
    def __init__( self ):
        self.name = "Base2"
        super( Base2, self ).__init__( )
    def getName( self ):
        return self.name
    def getB1Name( self ):
        return super( Base2, self ).getName( )


>>> b2 = Base2( )
>>> b2.getName( )
'Ancestor'
>>> b2.getB1Name( )
'Ancestor'

我无法理解结果。我期待 b2.getName() 的结果是“Base2”,而 b2.getB1Name() 的结果是“Base1”

4

2 回答 2

4

当您调用该super函数时,您基本上是跳入Ancestor类的构造函数并在那里执行代码。在构造函数中,将名称设置为"Ancestor",覆盖基类中的新名称。

如果您调用super每个构造函数的第一行,它应该返回正确的名称。


但是,请注意,getB1Name函数 inB2将始终返回字符串"Base2"——该name变量被简单地覆盖并且不会以任何方式“隐藏”。

可以使用双下划线变量,它会自动进行一些名称修改,以便保留“阴影”行为,但一般来说,更简洁的解决方案是简单地使用不同的变量名称,并设计代码以便您不需要两个不同版本的相同属性浮动。

于 2013-09-16T18:47:56.827 回答
3

self指的是实例,而不是类。你只有一个实例,所以所有的self引用都指向同一个对象。在Base2.__init__此对象上设置名称。然后调用super,它调用Base1.__init__,它在同一个对象上设置一个新名称,覆盖旧名称。

如果你真的需要,你可以使用双下划线属性来实现你想要的。

于 2013-09-16T18:48:49.030 回答