【问题标题】:Class attribute not showing up as expected类属性未按预期显示
【发布时间】:2015-03-25 03:42:10
【问题描述】:

我不明白为什么以下代码在 __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) )

【问题讨论】:

  • 明显的错误是你__init__ 基类两次(一次是明确的,一次是super - 失去其中一个!),但这并不能解释你观察到的错误。
  • 引发错误是因为loadUi 在设置die1 之前在您的类实例(您将其作为self 传递给它)上调用了__str__
  • 感谢您指出双重构造函数调用,经过一夜睡眠,我自己也注意到了!然而,ekhumoro 解决了这个问题!谢谢!愿意进一步评论吗?我正在从 PyQt4 切换到 PyQt5,并且总是在我的代码之外编译 ui。我以为我需要在设置信号之前加载 ui,这是真的吗?另外为什么 loadUi 会在我的类上调用 str 方法?
  • 如果你在 python 3x 上,你可以在没有类的情况下调用父方法。 ''super().__init__(父)''

标签: python python-3.x pyqt5


【解决方案1】:

如 cmets 中所述,引发错误是因为在设置 die1 之前,loadUi 在类实例(即self)上调用了__str__

uic 模块这样做的原因为什么是因为它在解析ui 文件时收集了大量调试信息,其中包括记录作为baseinstance 参数传递的对象loadUi.

不幸的是,它通过(间接)调用__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()
            ...

【讨论】:

    【解决方案2】:

    实际答案:在您创建dies 之后uic.loadUi 调用移至

    代码注释:

    • 只调用一次构造函数(不是一次作为QMainWindow 和一次作为super
    • 使用%s 时,您无需同时调用str()——%s 就是这样做的。
    • 如果只编写 Python3 代码,您的 super 调用可以省略 Dice, self 部分而只是 super().__init__(parent)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多