当我创建一个threading.Thread
类时,为什么要强制使用threading.Thread.__init__(self)
或{
例如:
class Threader(threading.Thread):
def __init__(self, _fp, _q):
threading.Thread.__init__(self)
self.path = _fp
self.queue = _q
def run(self):
# Do stuff
或者
^{pr2}$两种方法都有效,而且做的事情大致相同。但是,如果我删除.__init__()
方法中的任何一个,我将在堆栈中收到:from thread.start(): thread.__init__() not called
。
不应该定义我自己的def __init__()
“替换”.__init__()
方法吗?
我读过this另一个SO post,它与我的想法一致,但是得到了相同的堆栈错误。
考虑这个简化的例子:
我们已经创建了
dog
的子类,名为chihuahua
。这个类的用户可以合理地期望它在所有默认方面都像狗一样,除了我们已经覆盖的特定方面(它发出的声音)。但是请注意,正如您所指出的,新的子类__init__
替换了基类__init__
。完全替换。与C++不同,基类初始化代码是在创建子类实例时自动调用的EM>非EEM >。因此,当您创建一个chihuahua()
时,self.legs = 4
永远不会运行。结果,这种狗到处乱跑,根本不知道它有多少条腿。因此,你可能会争辩说它不是一只功能齐全的狗,而且如果它在试图表演复杂的把戏时摔倒了,你不应该感到惊讶。在作为子类设计器,您有两个选项来解决此问题。第一个是在子类中显式地重新实现
self.legs = 4
行。好吧,这在这个例子中可以很好地工作,但一般来说这不是一个很好的选择,因为它违反了DRY原则,即使在您确实知道要编写什么代码以及如何维护它的情况下。在更复杂的例子中(比如你的Thread
子类),你大概不知道。第二种选择:显式地调用超类初始值设定项并让它自己去做。在定义您自己的
__init__
覆盖基类。但是基__init__
为使线程可运行而做的所有工作呢?它通常创建的所有变量和状态都丢失了。除非你把这些都藏在自己身上(为什么要这样做?)当然,这条线是完全无法解开的。在当然,并不是所有的类都需要
__init__
,但绝大多数都需要。即使对那些不这样做的人来说,调用__init__
也是无害的——它只会转到object.__init__
并且在实现者认为__init__
是有用的情况下对子类进行验证。在相关问题 更多 >
编程相关推荐