2010-09-12 98 views
4

这跟在几个小时前我问过的一个问题。对基类行为感到困惑

我有这样的代码:

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)

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

回答

4

您定义它的方式B没有任何属性。当你做print a时,a引用__init__方法中的局部变量a,而不是任何属性。

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

+0

啊,我现在明白了。谢谢! – Jeremy 2010-09-12 14:57:12

+0

我是否正确地调用'b'类的属性或者是否存在其他一些Pythonic术语? – Jeremy 2010-09-12 15:01:12

+0

嗯,最重要的是,'实例变量'和'实例属性'有什么区别? – Jeremy 2010-09-12 15:02:43

2

在你的第二个代码,调用print a作品,因为你要打印作为参数传递给B的__init__函数传递的变量,而不是self.a变量(这是不是因为A.__init__初始化不叫)。一旦离开__init__功能的范围,您将无法访问a

+0

所以'a'类似于类属性? – Jeremy 2010-09-12 14:55:04

1

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

1

要解决这个问题,你需要使用

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

请务必声明类作为新的样式对象,你已经做的事情

[编辑:澄清]

+2

You mean't'super(B,self).__ init __(a)'I guess :) – user225312 2010-09-12 14:57:44