对基类行为感到困惑
这跟在几个小时前我问过的一个问题。对基类行为感到困惑
我有这样的代码:
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
是哪个类的属性 - 子类或超类?
您定义它的方式B
没有任何属性。当你做print a
时,a
引用__init__
方法中的局部变量a
,而不是任何属性。
如果用print self.a
替换print a
,您将收到与以前相同的错误消息。
在你的第二个代码,调用print a
作品,因为你要打印作为参数传递给B的__init__
函数传递的变量,而不是self.a
变量(这是不是因为A.__init__
初始化不叫)。一旦离开__init__
功能的范围,您将无法访问a
。
所以'a'类似于类属性? – Jeremy 2010-09-12 14:55:04
简短的回答是,__init__
不是其他语言的意义上的构造函数,如C++。在创建“裸”对象后,它实际上只是一个在对象上运行的函数。 B的__init__
函数通常负责调用A的__init__
,但它不必 - 如果A.__init__
永远不会被调用,那么A的属性a
不会被添加到该对象,因此当您尝试访问时会出现错误它。
要解决这个问题,你需要使用
class B(A):
def __init__(self, b, a):
super(A, self).__init__(a)
请务必声明类作为新的样式对象,你已经做的事情
[编辑:澄清]
You mean't'super(B,self).__ init __(a)'I guess :) – user225312 2010-09-12 14:57:44
啊,我现在明白了。谢谢! – Jeremy 2010-09-12 14:57:12
我是否正确地调用'b'类的属性或者是否存在其他一些Pythonic术语? – Jeremy 2010-09-12 15:01:12
嗯,最重要的是,'实例变量'和'实例属性'有什么区别? – Jeremy 2010-09-12 15:02:43