Когда использовать конструктор типажей Instance() и вопросы о коде учебника traitsUI

У меня есть вопрос относительно урока Traitsui Гаэля Вароко. Во фрагменте кода 7 он создает класс CaptureThread для создания потока для получения изображений с камеры. Он также делает класс камеры.

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) Почему в определении класса камеры он делает Capture_thread чертой, вызывая Instance(CaptureThread)? CaptureThread — это просто класс потока, зачем нам делать из него экземпляр типажа?

2) В классе CaptureThread он использует поле self.display.string и self.wants_abort. Эти два поля не передаются через метод конструктора, а назначаются вне определения класса классом Camera. Это лучшая практика? Так как если бы пользователь CaptureThread забыл задать эти два поля, то возникла бы ошибка. Есть ли какие-то разумные рекомендации, чтобы знать, когда я могу назначать такие вещи, или я должен использовать конструктор для их назначения?

Я надеюсь, что эти вопросы имеют смысл, и что это правильное место, чтобы задать их! Спасибо, labjunky


person labjunky    schedule 10.09.2013    source источник


Ответы (1)


  1. capture_thread = Instance(CaptureThread) не создает экземпляр CaptureThread. Это больше похоже на объявление, которое используется классом Camera при создании класса. Он сообщает этому классу Camera, что у него будет атрибут с именем capture_thread, который должен быть экземпляром CaptureThread или None и по умолчанию будет иметь значение None. Это значение по умолчанию позволяет проверить, инициализирован ли self.capture_thread, в противном случае создайте его логику в _start_stop_capture_fired() немного чище, по крайней мере, на вкус некоторых людей.

  2. Для подклассов threading.Thread да, это один идиоматический способ сделать это, хотя и не единственный. Thread уже имеет конкретную реализацию __init__, и вы можете переопределить его, чтобы сделать что-то другое, но понятно, что в данном случае автор избегал бы этого.

    Это не идиоматический способ инициализации HasTraits подклассов, который действительно должен использовать аргументы ключевого слова.

person Robert Kern    schedule 11.09.2013