应该避免通配符导入吗?
Posted
技术标签:
【中文标题】应该避免通配符导入吗?【英文标题】:Should wildcard import be avoided? 【发布时间】:2011-04-06 14:52:25 【问题描述】:我正在使用 PyQt 并且遇到了这个问题。如果我的导入语句是:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
然后 pylint 会给出数百个“未使用的导入”警告。我很犹豫是否要关闭它们,因为可能还有其他未使用的导入实际上很有用。另一种选择是这样做:
from PyQt4.QtCore import Qt, QPointF, QRectF
from PyQt4.QtGui import QGraphicsItem, QGraphicsScene, ...
我最终在 QtGui 线上有 9 个课程。还有第三种选择,即:
from PyQt4 import QtCore, QtGui
然后在我使用它们时为所有类添加 QtCore 或 QtGui 前缀。
在这一点上,我不知道我最终会在我的项目中做哪一个,尽管从我的角度来看,最后一个似乎是最痛苦的。这里的常见做法是什么?使用一种风格而不是另一种风格是否有技术原因?
【问题讨论】:
我为这个问题加星标是因为我想看到答案,但我也很好奇为什么有人会这样做。通常我只导入我需要的东西,我知道我需要什么,所以我只导入那些东西。也许我很天真,但在我看来,键入 QtCore.something 的“痛苦”会比浪费处理器时间导入数百个未使用的项目更好(自动填充?)。我知道这样做会让我在代码审查中大吃一惊。他们会询问我使用的每个导入。 我同意你的专业代码,但对于个人脚本或项目,这不是什么大问题。特别是因为导入可能会在程序启动时发生,所以它不应该影响运行性能,只会影响启动时间。 相关:Why is “import *” bad? 【参考方案1】:您的问题标题的答案是“是”:我建议永远不要使用from ... import *
,我在另一个最近的答案中讨论了原因。简而言之,限定名称很好,裸名称非常有限,因此“第三个选项”在您呈现的人中是最佳选择(因为您将使用限定名称,而不是裸名称)。
(合格名称 wrt 裸名称的优点包括易于伪造/模拟以用于测试目的,降低了因意外重新绑定引起的未注意到错误的风险,能够“半伪造”“跟踪类”中的***名称目的是准确记录您正在使用的内容并简化分析等活动 - 缺点,几乎没有......另请参阅 Python Zen 中最后但并非最不重要的公案,import this
at交互式解释器提示)。
同样好,如果你不喜欢说QtCore.whatever
的7 个额外字符,那就是缩写--from PyQt4 import QtCore as Cr
和from PyQt4 import QtGi as Gu
(然后使用Cr.blah
和Gu.zorp
)等等。像所有缩写一样,它是简洁和清晰之间的风格权衡(您更愿意将变量命名为 count_of_all_widgets_in_the_inventory
、num_widgets
还是 x
?通常中间选择是最好的,但并非总是如此;-)。
顺便说一句,我不会在单个 from
或 import
语句中使用多个 as
子句(可能会令人困惑),我宁愿有多个语句(如果有任何导入也更容易调试)问题,如果您将来更改导入,则进行编辑,...)。
【讨论】:
qualified 的另一个优点 - 你不能像 PyQt 这样在一个巨大的库中导入所有东西,然后不小心导致与你不知道的东西发生命名空间冲突。 可能有错别字,"import from this" -> "import this" 在我看来,这个答案对于一种特殊情况已经过时了:最好在“init.py”文件中使用通配符导入来从定义__all__
的模块导入。
@sunqiang:不,这不是错字——试试看。【参考方案2】:
import *
也有很好的案例。 IE。 Django 开发人员拥有许多配置文件并使用 import * 链接它们是很常见的:
settings.py:
FOO = 1
BAR = 2
DEBUG = False
test_settings.py:
from settings import *
DEBUG = True
在这种情况下,import *
的大多数缺点都变成了优点。
【讨论】:
这样的文件是一击奇迹,旨在通过明星导入。 PyQt4.QtGui 不合格! C-; @Phlip 同意,但是这篇文章的标题是“应该避免通配符导入吗?”不是“在 PyQt4 中应该避免通配符导入吗?” 我认为这个答案需要展示好的场景,而不是仅仅选择主要场景并说它很糟糕。这就像说“我应该在路上开车吗”,有人说“是”,有人说“如果有‘禁止进入’标志就不行”。【参考方案3】:Python doc 说:
尽管某些模块设计为仅导出后面的名称 使用 import * 时的某些模式,仍然被认为是错误的 在生产代码中练习。
它可能有副作用并且很难调试
就我个人而言,我使用的是import
而不是from import
,因为我在文件开头发现了可怕的大声明,我认为它使代码更具可读性
import PyQt4
PyQt4.QtCore
如果模块名太长,可以用as
关键字在本地重命名。例如:
import PyQt4.QtCore as Qc
【讨论】:
所以如果你有一个鼠标事件处理程序,例如,你可能会有这样的一行:“if event.buttons() & PyQt4.QtCore.Qt.LeftButton:”?这似乎不像“if event.buttons() & Qt.LeftButton:”那样可读 如果太长我会这样做:在 Qc 处导入 PyQt4.QtCore.Qt,然后在 Qc.LeftButton 处导入 我的意思是:导入 PyQt4.QtCore.Qt 作为 Qc【参考方案4】:我对我使用的 PyQt 模块使用“import *”,但是我把它们放在自己的模块中,所以它不会污染用户的命名空间。例如
在 qt4.py 中:
从 PyQt4.QtCore 导入 * 从 PyQt4.QtGui 导入 *那就这样用吧
导入qt4 应用程序 = qt4.QApplication(...)【讨论】:
这不等同于“import PyQt4.QtCore as qt4”吗?我想如果你这样做的话,你需要为 QtCore 和 QtGui 单独命名空间,但这似乎不是一件坏事。 如果在 qt4.py 中只有一个导入,它是等价的。我没有发现 QtCore、QtGui 等之间的区别……在编程时非常有用。 这是一个很好的解决方案,可以绕过源文件顶部的垃圾。 Qt 模块不会相互冲突,所以据我所知,这不会带来任何问题。【参考方案5】:PyQt4 的导入是一种特殊情况。 有时我会选择“第一个选项”进行快速而肮脏的编码,当代码越来越长时将其转换为“第二个选项”。 命名空间冲突在这里可能没什么大不了的,我还没有看到其他包的名称以大“Q”开头。每当我完成一个 PyQt4 脚本时。将“从 PyQt4.QtGui import *”转换为……像“
from PyQt4.QtGui import (QApplication, QDialog, QLineEdit, QTextBrowser,
QVBoxLayout)
" 仅供参考,parentheses for multi-line import 在这里很方便。
【讨论】:
【参考方案6】:在一般情况下,我绝对反对import *
。
对于PySide2
,有一种罕见的例外情况适用:
from PySide2 import *
是从PySide2
导入所有已知模块的模式。这
导入很方便,因为导入总是正确的。
该常数是从CMAKE
生成器计算出来的。非常有帮助
在交互式控制台中快速尝试某些东西时,也在自动化测试中。
对于高级用法,也有意义
直接使用PySide2.__all__
变量,它实现了这个
特征。 PySide2.__all__
的元素按依赖排序,
所以首先是QtCore
,然后是QtGui
,QtWidgets
,......等等。
【讨论】:
以上是关于应该避免通配符导入吗?的主要内容,如果未能解决你的问题,请参考以下文章