一个非常大的__init__有问题吗?

7 投票
4 回答
2614 浏览
提问于 2025-04-16 04:20

我正在用Python写一个图形用户界面(GUI),这个界面是用Tkinter模块搭建的。我使用一个类来定义这个GUI,因为这样可以更方便地给按钮传递命令,也让整个代码更容易理解。

我的GUI初始化部分大约有150行代码。为了让这部分更容易理解,我把__init__函数写成了这样:

def __init__(self, root):
    self.root = root
    self._init_menu()
    self._init_connectbar()
    self._init_usertree()
    self._init_remotetree()
    self._init_bottom()

在这里,_init_menu()_init_connectbar()等等负责所有的初始化工作。这样做让我的代码更容易跟上,也避免了__init__变得太复杂。

不过,这样做也带来了作用域的问题。因为我在_init_connectbar()中定义的一个输入框(Entry widget)是在这个函数的作用域内,而不是类的属性,所以我在类的其他方法中无法引用它。

我可以通过在__init__中做大部分初始化来解决这些问题,但这样我就失去了最开始那种结构清晰的好处。

我应该扩展__init__,还是找其他方法把这些控件引入到类的作用域中呢?

4 个回答

2

在我看来,你应该把小部件(widgets)存储为实例变量,这样你就可以在任何方法中引用它们。就像大多数编程语言一样,当函数变得太大时,代码的可读性就会下降,所以你把初始化代码拆分开的做法是个好主意。

当一个类的内容太多,放不下一个源文件时,你也可以通过使用混合类(mix-in classes)来拆分这个类,这有点像C#中的部分类(partial classes)。

举个例子:

class MainGuiClass(GuiMixin_FunctionalityA, GuiMixin_FunctionalityB):
    def __init__(self):
        GuiMixin_FunctionalityA.__init__(self)
        GuiMixin_FunctionalityB.__init__(self)

当图形用户界面(GUI)包含不同功能时,这种做法就特别有用,比如有一个配置标签、一个执行标签等等。

5

你可以选择把一些小部件的引用存储在实例变量里,或者把它们返回(不过要注意只返回最少的一部分;这样可以减少耦合)。然后在__init__方法里把这些引用存储在局部变量中,再把相关的引用作为参数传递给后面的构造辅助函数。后者的做法更简洁,但需要确保各个部分之间的关系足够松散,这样才能创建一个合理的顺序来实现这一点。

2

为什么不把你需要引用的小部件(widgets)做成实例变量呢?我通常都是这么做的,这似乎是一个很常见的方法。

比如:

self.some_widget

撰写回答