当从线程继承时调用超类构造函数

问题描述:

我很好奇,为什么当我的类继承Thread时,我不能调用super(Thread, self).__init__()而不是Thread.__init__(self)。你能帮我理解这个问题吗?当从线程继承时调用超类构造函数

#!/usr/bin/python 

from threading import Thread 
from Queue import Queue 
class ThreadManager(object): 

    def work(self, items): 
     q = Queue() 
     for item in items: 
      q.put(item) 

     print q.qsize() 

     p = Worker() 
     p.start() 
     p.join() 

class Worker(Thread): 
    def __init__(self): 
     # Why doesn't this work? 
     #super(Thread, self).__init__() 

     Thread.__init__(self) 

    def run(self): 
     print 'thread running' 

def main(): 
    items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] 
    tm = ThreadManager() 
    tm.work(items) 

if __name__ == "__main__": 
    main() 

我很好奇,为什么我不能叫super(Thread, self).__init__()而不是Thread.__init__(self)当我的类从Thread继承。

因为那不是super如何工作。您必须将您的自己的类型作为第一个参数,以便它可以搜索该类型的下一个祖先。如果你通过它Thread,你要求一个Thread的祖先。

如果你的父类是有规律的新型Python类,这样做不对通常意味着你跳过一个祖先类,这可能是无害的,也可能似乎工作,但实际上没有做正确的事。但threading.Thread有具体的检查,以确保它得到正确的初始化,所以你可能会得到这样的事情:

AssertionError: Thread.__init__() was not called 

如果你的父类是C扩展级,它可能没有任何祖,它可能不会实现super即使它,所以你通常会得到一个这样的错误。

如果您想了解所有这些工作方式(因为上面链接的文档不一定是最好的介绍性讨论),您可能需要阅读Python's super() considered super

因此,简言之:我用用

super(Worker, self).__init__() 
+0

所有例子字母的类名,所以我糊涂了!谢谢你的回答! – 2013-03-01 02:01:33

+0

@DavidM.Coe:这是一个很好的观点......它应该提醒我们其他人停止编写例子,其中A从B继承,反之亦然,并提出实际名称...... – abarnert 2013-03-01 02:10:41