我试图了解在python中使用继承时何时初始化超类。最初,我认为只要声明一个从超类继承的类,例如class my_class(superclass(:,就可以使该子类使用超类的所有属性和方法。这对来自Java的人来说是有意义的。然后我读到Python强制我们初始化超类,然后才能在子类中实现它们,或者使用超类init((或super((init((。然后我遇到了这段代码,其中我没有初始化父类,但是Python允许我在没有初始化父级的情况下从超类访问self.queue属性。我读过Python文档,有时我想我知道它们的意思,而其他一些我不知道。有人能向我解释一下我们什么时候必须初始化子类中的超类吗?
class QueueError(IndexError):
pass
class Queue:
def __init__(self):
self.queue = []
def put(self,elem):
self.queue.insert(0,elem)
def get(self):
if len(self.queue) > 0:
elem = self.queue[-1]
del self.queue[-1]
return elem
else:
raise QueueError
class SuperQueue(Queue):
def isempty(self):
if not self.queue:
return True
else:
return False
que = SuperQueue()
que.put(1)
que.put("dog")
que.put(False)
for i in range(4):
if not que.isempty():
print(que.get())
else:
print("Queue empty")
通常,如果在子类中重写__init__
,则应仅调用超级__init__
方法。如果扩展超类,这是必要的。但是,如果要覆盖整个__init__
,也可以省略超级调用。
示例:
您有一个类A
,它有一个属性value1
。现在你需要第二个属性,所以你用B
来划分A
的子类,并覆盖你调用超类(A
(的__init__
,所以A
可以设置value1
,而在B
中你不能设置value2
但现在您需要C
中的一些其他属性,但需要与A
中相同的方法。因此,您可以完全覆盖__init__
,并省略对A
的超级调用。
class A:
def __init__(self, value1):
print("Initialize A")
self.value1 = value1
class B(A):
def __init__(self, value1, value2):
super().__init__(value1)
print("Initialize B")
self.value2 = value2
class C(A):
def __init__(self, value3):
print("Initialize C")
self.value3 = value3
a = A("foo")
b = B("foo", "bar")
c = C("baz")
print(a.value1)
print(b.value1, b.value2)
print(c.value3)
print(c.value1)
输出
$ python main.py
Initialize A
Initialize A
Initialize B
Initialize C
foo
foo bar
baz
Traceback (most recent call last):
File "main.py", line 27, in <module>
print(c.value1)
AttributeError: 'C' object has no attribute 'value1'
您可以看到C
没有用value1
初始化,因为C
没有调用A
的__init__
。