How to avoid global variables
在阅读python文档和各种邮件列表时,我总是阅读一些看起来有点像教条的东西。全局变量应该避免像地狱一样,它们是糟糕的设计…好吧,为什么不呢?但在现实生活中,我不知道如何避免这种模式。
假设我有一个GUI,可以从主菜单加载几个文件。与加载的文件相对应的文件对象可以通过所有GUI使用(例如,图像查看器,它将显示图像,并且可以通过不同的对话框/插件对其执行各种操作)。
建造以下设计真的有什么问题吗?
- menu.py——>文件将从此处加载
- main.py-->此处可以使用加载的文件对象
- dialog1.py-->或此处
- dialog2.py->或那里
- dialog3.py->或那里
- …
- 环球公司
其中globals.py将存储一个字典,其键是加载文件的名称和相应文件对象的值。然后,从那里,需要这些数据的代码的各个部分将通过弱引用访问它。
对不起,如果我的问题看起来(或是)愚蠢,但你看到任何优雅或全球免费的选择吗?一种方法是将加载的数据字典封装在main.py的主应用程序类中,将其视为GUI的中央访问部分。但是,这也会带来一些复杂的情况,因为这个类应该可以从所有需要数据的对话框中轻松访问,即使它们是数据的直接子类。
非常感谢你的帮助
- 全局变量不是坏事。邪恶的是把它当作一个可变的变量。全局变量应尽可能保持静态和"不变"。如果你不得不改变globals.py中的字典内容,那就没用了。除此之外,因为阅读是可以的。
- 是的,全局"常量"是可以的,应该避免全局"变量"。
- 好吧,我明白你们两个的意思,但是我仍然没有看到一个有效的python替代我提出的设计,在这个设计中,加载的数据字典可能会随着时间的推移而发展(新加载的文件,删除的文件)
应该避免使用全局变量,因为它们会抑制代码重用。多个小部件/应用程序可以很好地活在同一个主循环中。这允许您将您现在所认为的单个GUI抽象到一个库中,该库根据请求创建此类GUI,以便(例如)单个启动程序可以启动多个共享同一进程的顶级GUI。
如果使用全局变量,这是不可能的,因为多个GUI实例将胜过彼此的状态。
全局变量的替代方法是将所需的属性与顶级小部件相关联,并创建指向相同顶级小部件的子小部件。然后,例如,菜单操作将使用它的顶级小部件访问当前打开的文件,以便对其进行操作。
- 型我将同意静态成员变量/属性(但不一定是根据实例属性,如果只是为了常量,读取目的)。但根据需要,拥有一些常量并不是那么糟糕。只需确保他们了解python可以做什么,不能做什么:p
- 型如果我理解正确的话,这样的设计就像一种树,其中加载的数据字典将存储为根顶级小部件的属性。然后,应用程序的所有小部件都可以通过调用"TopLevelParent"方法来访问它。
- 型您可以有一个存储文件名和顶级数据的MainModel。使用qt,您将拥有主窗口,它将存储文件名和顶级数据。打开和写入文件的事件通常在顶级对象中处理,低级对象不需要知道文件名。
- 型@EikeGTK也允许这样做,这就是我描述的架构。这样,您将自动获得与全局变量相同的便利级别,但不会有缺点。我的回答的重点是要清楚地解释文学经常(令人信服地)做不到的缺点,这使这一行动受挫。
- 型@用户4815162342是的,确实。我的评论是为了回答佩莱格里尼·埃里克之前的评论。
- 型多谢各位。现在我明白了
我将通过将数据封装在一个或多个类中来管理全局数据,并为这些类实现BORG模式。看看为什么在python中borg模式比singleton模式更好
- 型请不要宣传博格模式。singleton的关键是您只有一个实例,这样可以节省内存并确保相同的行为。如果确实需要在不同的子类中拥有不同的实例,那么有一些方法可以做到这一点,而不影响每个类拥有一个实例的基本单例需求。
- 型无论是borg模式还是singleton模式都不能缓解全局变量的主要问题,即只有一个全局状态。事实上,单例模式只是一个很好的面向对象的界面,与共享的全局状态相连接,这正是文献所说的(没有正确解释为什么)要避免的操作。
- 型我更喜欢一种实用的方法:全局变量aka singleton aka borg模式只有在代码编写和读取时才是危险的。全局记录器(所有客户端都写入)和数据库连接池(所有客户端都读取)都不危险。如果开发人员遵循书籍,但不应忘记背景,这是很好的。
- 型@用户4815162342内存点取决于BORG实例的数量,如果您有数千个实例,我假设您设计中的其他一些实例已损坏。我不明白为什么"borg类"的实例不应该显示相同的行为,共享的内部状态是borg模式的核心。