2015-03-25 39 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)