首页 > 解决方案 > Python 在 init 之外定义 gui 变量

问题描述

PySide2用来定义我的工具的界面,我通常会在外面初始化所有界面项__init__,以免它膨胀(任何其他重要的变量都留在里面__init__)。

对我来说不幸的是,我使用 PyCharm 作为我的编辑器,它给了我很多警告:

在 __init __ 之外定义的实例属性 'foobar'

这是我将要做的一个简单示例:

from PySide2 import QtWidgets


class MyTool(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(MyTool, self).__init__(parent)

        self.create_gui()

    def create_gui(self):
        # Complains about all variables below!

        self.awesome_checkbox = QtWidgets.QCheckBox(parent=self)

        self.awesome_button = QtWidgets.QPushButton(parent=self)

        self.awesome_label = QtWidgets.QLabel(parent=self)

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(self.awesome_checkbox)
        self.main_layout.addWidget(self.awesome_button)
        self.main_layout.addWidget(self.awesome_label)
        self.setLayout(self.main_layout)

现在我知道一种解决方案是在__init__as中初始化这些变量None,但我可以有相当复杂的接口,所以它会很长。

我的问题是,如果我目前正在做的事情真的是亵渎神灵?我知道变量在技术上是外部__init__的,但是无论如何都在构造函数中调用了该方法!

标签: pythonuser-interfacepyside2

解决方案


好吧,简短的回答是:不,这不是“真正的亵渎”。

创建所有实例属性并确保它们在初始化程序中处于一致状态被认为是一种很好的做法,因为它使代码更易于阅读(您只有一种方法可以阅读以了解您的对象具有哪些属性)并避免潜在的 AttributeError 时属性是由在访问属性之前可能并不总是被调用的方法创建的。这就是为什么大多数 linter 会(默认情况下)警告您这一点,这本身就是一件好事,因为它可以帮助您在潜在错误进入生产之前发现它。

现在确实存在将实例初始化的一部分委托给不同方法的情况,即当这些属性相互依赖和其他一些外部因素并且可能必须在实例的生命周期期间一起重置/更新时,或者当您想让子类覆盖初始化的这一部分,而不必覆盖__init__()方法本身(参见 GOF 的“模板方法”模式)。

对于具有复杂初始化的类(这是 GUI 组件的典型情况),出于可读性原因,将设置拆分为不同的方法也是有意义的 - 就可读性而言,50 多行初始化程序并不是真正最佳的 - 所以就我而言,我可能会做一些类似的改进,可能会有一些改进:首先将其设为“受保护”方法(将其命名为_create_gui()- 前导下划线是受保护属性/方法的命名约定),然后添加一个保护以防止该方法被执行两次(假设该方法只应该从初始化程序调用一次并且不应该是公共 API,当然)。然后我会添加一些 linter 指令(这些是 linter 寻找的特殊格式的注释),以使 linter 和阅读此代码的任何人都清楚这样做是一个深思熟虑的设计选择,而不是一个新手错误。


推荐阅读