2015-03-25 3 views
1

Я не понимаю, почему следующий код возвращает ошибку AttributeError: 'Dice' object has no attribute 'die1' в методе __str__. Я знаю, что создал его, и мой отладчик показывает его как атрибут класса. Что не так с этим (простым) кодом?Атрибут класса не отображается, как ожидалось

class Dice(QMainWindow) : 
     """A game of Dice.""" 

     def __init__(self, parent = None): 
      """Build a game with two dice.""" 

      QMainWindow.__init__(self, parent) 

      super(Dice, self).__init__(parent) 
      uic.loadUi("Dice.ui", self) 

      self.die1 = Die() 
      self.die2 = Die() 
      self.rollButton.clicked.connect(self.rollButtonClickedHandler) 


     def __str__(self): 
      """String representation for Dice. 
      """ 
      return "Die1: %s\nDie2: %s" % (str(self.die1), str(self.die2)) 
+0

Что, очевидно, не так, что вы '__init__' базового класса дважды (один раз в явном виде и один раз' super' - потерять один из их!), но это не объясняет ошибку, которую вы наблюдаете. –

+0

Ошибка возникает из-за того, что 'loadUi' вызывает' __str__' в экземпляре класса (который вы передали ему как 'self') перед установкой' die1'. – ekhumoro

+0

Спасибо за указание на вызов двойного конструктора, я заметил это сам, после ночного сна! Однако эхуморо прибил проблему! Благодаря! Хотите прокомментировать дальше? Я переключаюсь с PyQt4 на PyQt5 и всегда скомпилировал ui вне моего кода.Я думал, что мне нужно будет загрузить ui перед настройкой сигналов. Это правда? Также почему loadUi вызывает метод str в моем классе? – Arana

ответ

0

Как было отмечено в комментариях, возникает ошибка, потому что loadUi вызовы __str__ на экземпляр класса (т.е. self) до die1 был установлен.

Причина почемуuic модуль делает это потому, что он собирает много отладочной информации во время разбора файла ui, и включает в себя вход объекта, переданного в качестве аргумента baseinstanceloadUi.

К сожалению, это делает (косвенно) вызов __str__, когда он, вероятно, должен звонить __repr__. (Или, возможно, просто не регистрировать информацию отладки на всех при вызове функций API python. В интерфейсе командной строки есть опция для , включающая отладку, но похоже, что это контролирует только отображение отображаемой информации, а не он собирается в первую очередь).

Конечно, естественно, что нужно позвонить по телефону loadUi в кратчайшие сроки во время инициализации - так же, как и с setupUi. Но независимо от того, как вы загружаете ui в свое приложение, uic будет генерировать код точно так же. Единственная разница с loadUi заключается в том, что он вызывает exec() на сгенерированном коде во время выполнения, тогда как с pyuic тот же код просто импортируется как статический модуль.

Существует несколько способов решения вашей непосредственной проблемы. Лично я думаю, что я выбрал бы предварительно инициализирует die1/die2, как атрибуты класса:

class Dice(QMainWindow) : 
     """A game of Dice.""" 
     die1 = die2 = None 

     def __init__(self, parent=None): 
      """Build a game with two dice.""" 
      super().__init__(parent) 
      uic.loadUi("Dice.ui", self) 
      self.die1 = Die() 
      self.die2 = Die() 
      ... 
0

Фактический ответ: переместить uic.loadUi вызов после вы создаете die с.

Комментарии Код:

  • только вызов конструктора один раз (не один раз, как QMainWindow и один раз как super)
  • При использовании %s, вам не нужно также назвать str() - это то, что %s делает.
  • Если писать Python3 только код, ваш super вызов может оставить вне Dice, self часть и просто super().__init__(parent)
Смежные вопросы