2015-03-25 32 views
1

我不明白,爲什麼下面的代碼在__str__方法返回一個錯誤AttributeError: 'Dice' object has no attribute 'die1'。我知道我已經創建了一個,我的調試器將它顯示爲一個類屬性。這個(簡單)代碼有什麼問題?類屬性沒有顯示出來,如預期

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'一次 - 失去一個他們!),但這並不能解釋你觀察到的錯誤。 – 2015-03-25 04:03:46

+0

由於'loadUi'在您的類實例(您將它傳遞給'self')的'die1'設置之前調用'__str__',所以會引發錯誤。 – ekhumoro 2015-03-25 05:54:23

+0

感謝您指出了雙重構造函數的調用,我注意到一個人,睡了一晚後!然而ekhumoro釘住了這個問題!謝謝!謹慎進一步評論?我正在從PyQt4切換到PyQt5,並且始終在我的代碼之外編譯ui。我想在設置信號之前我需要加載ui,這是真的嗎?另外爲什麼loadUi會在我的類中調用str方法? – Arana 2015-03-25 15:11:44

回答

0

正如評論指出的那樣,引發錯誤,因爲loadUi電話__str__的類實例(即self)之前die1已設置。

原因爲什麼uic模塊的確,這是因爲它收集了很多,同時解析ui文件的調試信息,這包括登錄爲loadUibaseinstance參數傳遞的對象。

不幸的是,它由(間接)調用__str__時,它可能需要調用__repr__做到這一點。 (或可能只是不記錄調用的Python API函數時,在所有調試信息。命令行界面有上調試切換的選項,但似乎這只是控制是否顯示已登錄信息,而不是是否它首先被聚集在一起)。

想要在初始化過程中儘早打電話給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)