对基类的行为感到困惑

时间:2010-09-12 14:40:03

标签: python

这是我几个小时前提出的一个问题。

我有这段代码:

class A(object):
    def __init__(self, a):
        print 'A called.'
        self.a = a

class B(A):
    def __init__(self, b, a):
        print 'B called.'

x = B(1, 2)
print x.a

这会产生错误:AttributeError: 'B' object has no attribute 'a',如预期的那样。我可以通过致电super(B, self).__init__(a)来解决这个问题。

但是,我有这段代码:

class A(object):
    def __init__(self, a):
        print 'A called.'
        self.a = a

class B(A):
    def __init__(self, b, a):
        print 'B called.'
        print a

x = B(1, 2)

谁的输出是:

B called.
2

为什么这样做?更重要的是,当我没有初始化基类时,它是如何工作的?另请注意,它不会调用A的初始值设定项。是因为当我做的时候:

def __init__(self, b, a)

我声明bB的属性?如果是,我如何检查b是哪个类的属性 - 子类还是超类?

4 个答案:

答案 0 :(得分:4)

您定义它的方式B没有任何属性。执行print a后,a会引用a方法中的本地变量__init__,而不是任何属性。

如果您将print a替换为print self.a,您将收到与以前相同的错误消息。

答案 1 :(得分:2)

在第二个代码中,调用print a是有效的,因为您将作为参数传递的变量打印到B的__init__函数,而不是self.a变量(由于{{未初始化) 1}}没有被调用)。一旦离开A.__init__函数的范围,您将无法访问__init__

答案 2 :(得分:1)

简短的回答是__init__不是其他语言(如C ++)意义上的构造函数。它实际上只是在创建“裸”对象后在对象上运行的函数。 B的__init__函数通常负责调用A的__init__,但它不必 - 如果A.__init__永远不会被调用,那么A的属性a就不会被调用添加到对象中,因此当您尝试访问它时会出现错误。

答案 3 :(得分:1)

要解决此问题,您需要使用

class B(A):
    def __init__(self, b, a):
        super(A, self).__init__(a)

确保将类声明为新样式对象,这是您已经在做的事情

[编辑:澄清]