何时使用trait Instance()构造函数,以及有关traitsUI教程代码的问题

时间:2013-09-10 10:26:09

标签: traits enthought traitsui

我对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

1 个答案:

答案 0 :(得分:2)

  1. capture_thread = Instance(CaptureThread)未生成CaptureThread的实例。在创建类时,它更像是Camera类消耗的声明。它告诉Camera类,它将具有名为capture_thread的属性,该属性应该是CaptureThreadNone的实例,并且默认为None。这个默认设置允许“测试self.capture_thread是否被初始化,否则创建它”_start_stop_capture_fired()中的逻辑更清洁,至少对某些人来说是这样。

  2. 对于threading.Thread子类,是的,它是一种惯用的方法,但不是唯一的方法。 Thread已经有一个特定的__init__实现,你可以覆盖它来做其他事情,但是在这种情况下作者会避免这样做是可以理解的。

    这是初始化HasTraits子类的惯用方法,确实是使用关键字参数。