我对Gael Varoquaux的traitsui tutorial有疑问。 在代码片段7中,他创建了一个CaptureThread类,用于生成从摄像机拍摄图像的线程。他还制作了一个Camera类。
class TextDisplay(HasTraits):
string = String()
view = View(Item('string', show_label=False, springy=True, style='custom'))
class CaptureThread(Thread):
def run(self):
#self.display is set outside the class definition by the caller
self.display.string = 'Camera started\n' + self.display.string
n_img = 0
while not self.wants_abort:
sleep(0.5)
n_img += 1
self.display.string = ' %d image captured\n' % n_img \
+ self.display.string
self.display.string = 'Camera stopped\n' + self.display.string
class Camera(HasTraits):
start_stop_capture = Button()
display = Instance(TextDisplay)
capture_thread = Instance(CaptureThread)
view = View( Item('start_stop_capture', show_label=False))
def _start_stop_capture_fired(self):
if self.capture_thread and self.capture_thread.isAlive():
self.capture_thread.wants_abort = True
else:
self.capture_thread = CaptureThread()
self.capture_thread.wants_abort = False
self.capture_thread.display = self.display
self.capture_thread.start()
我对此代码有两个问题:
1)为什么在Camera类定义中他通过调用Instance(CaptureThread)使capture_thread成为Trait? CaptureThread只是一个线程类,我们为什么要从中创建一个特征实例呢?
2)在CaptureThread类中,他使用字段self.display.string和self.wants_abort。这两个字段不是通过构造函数方法传入的,而是由Camera类在类定义之外分配。这是最好的做法吗?因为如果CaptureThread的用户忘记设置这两个字段,则会发生错误。是否有一些明智的指导方针可以知道何时可以分配这样的东西,或者我应该使用构造函数来分配它们?
我希望这些问题有意义,而且这是问他们的合适地方! 谢谢,labjunky
答案 0 :(得分:2)
capture_thread = Instance(CaptureThread)
未生成CaptureThread
的实例。在创建类时,它更像是Camera
类消耗的声明。它告诉Camera
类,它将具有名为capture_thread
的属性,该属性应该是CaptureThread
或None
的实例,并且默认为None
。这个默认设置允许“测试self.capture_thread
是否被初始化,否则创建它”_start_stop_capture_fired()
中的逻辑更清洁,至少对某些人来说是这样。
对于threading.Thread
子类,是的,它是一种惯用的方法,但不是唯一的方法。 Thread
已经有一个特定的__init__
实现,你可以覆盖它来做其他事情,但是在这种情况下作者会避免这样做是可以理解的。
这是不初始化HasTraits
子类的惯用方法,确实是使用关键字参数。