[英]Python * imports
我通常被告知以下是不好的做法。
from module import *
主要原因(或者我被告知)是您可能会导入您不想要的东西,并且它可能会影响另一个模块中类似名称的 function 或 class 。
但是,PyQt 呢?
from PyQt4.QtCore import *
我见过的每个示例都是这样编写的,主要是因为从 Qt 导出的所有内容都以“Q”开头,因此不会影响任何内容。
共识是什么? 使用 * 进口总是不好的吗?
编辑:
为了清楚起见,这个问题专门针对使用 PyQt4。 这与我设计其他项目的方式无关。
基本上,我发现 PEP8 编码提高了我的代码可读性,除了导入 PyQt4 方面,所以直到现在我都没有理会纯粹主义者的皱眉。 但是现在我的开发组正在决定一个约定,我想知道这是否是“实用性胜过纯度”的场景,或者我是否应该接受它并处理可怕的 PyQt4 导入
from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......
这可能会演变成一场宗教战争。 这是您是否想明确或是否想避免过于冗长的问题。 一般来说,遵循Python 的 Zen ,最好是明确的,但有时人们只是觉得列出来自特定模块的每个导入并不实用。
我的一般规则是,如果我不编写模块,我不会全部导入。 我最大的恐惧实际上是编写可能已在导入模块中定义的局部变量。 因此,为了避免输入长模块名称,我使用 import as 功能。 以您的模块为例,我将执行以下操作:
import PyQt4.QtCore as qt
话虽如此,我编写了许多支持模块,我将导入所有内容。 就像 pyqt 模块一样,我用一个描述性的名称来命名它们,这有助于显示它来自哪个模块。
按评论编辑
当我使用 import* 时,我的支持模块不包含类或任何可以创建新实例的东西。 它们往往是仅修改现有实例的函数组。 为了帮助澄清我的观点:如果我是源代码的所有者并且我将是主要维护者,我将使用 import* 否则我将使用 import as。
我使用 import as 功能的另一个原因是允许我模拟模块以进行调试。 在我现在正在进行的一个项目中,我使用 pyVisa 与许多 GPIB 设备进行通信。 当我没有连接到设备 GPIB 网络时,我可以使用 dummy_visa 模块写入标准输出(以验证我发送的格式正确)并返回一个随机数(以测试我的应用程序)。 见下文
if visa_debug:
import dummy_visa as visa
else:
import visa
gpib = visa.Instrument("GPIB0::10")
gpib.write("MEAS:VOLT?")
对已经在命名约定中包含命名空间的模块(例如 PyQT 的Q*
)进行显式例外是完全合理的。 但是,我建议明确默认仍然是“不要使用它”,并在您的编码指南中简单地列出这个例外。
import *
is also acceptable when it is used as a namespace manipulation trick within an application (the two forms of that I am familiar with are optional C acceleration modules that are imported at the end of the pure Python version, and "flattening" a package __init__
中的命名空间)。 关键是导入模块和被导入模块都在同一组开发人员的控制之下,因此避免命名空间冲突完全在他们的控制范围内。
最后一个例外是为了方便交互式提示。
在其他情况下,最好要么导入特定名称,要么通过模块名称间接引用它们(或者,如果有一些常用的引用项,则同时执行以下操作:
import module # Can access any from module import a, b, c # 但是我们引用了很多,所以直接检索
我发现import *
被滥用了,并且可能成为维护方面的难题,所以我避免使用它,因为这个原因以及 state 的其他原因。 也就是说,我觉得简短的交互式会话没问题,例如from pylab import *
。
在生产代码中,对于像PyQt4.QtCore
这样您计划使用许多符号的包,我将使用以下语法之一来明确符号来自哪个命名空间:
from PyQt4 import QtCore
# explicit where the symbol came from
QtCore.QTime()
import PyQt4.QtCore as QT
# less desirable since you need to look in the header to find out what QT is
# but I still prefer it to import *
QT.QTime()
一般来说,如果您要使用from X import Y
,最好明确说明您要导入的内容。 这不仅是因为它更安全,还因为它使您的代码更具可读性(并且升级到您正在使用的第三方模块不会有太多可能意外破坏您的代码)。
在一些演示大包的代码示例中,例如 Qt 或 matplotlib,这些示例将使用from module import *
因为它们通常只从一个模块导入,这样可以节省键入并让示例代码切入主题。 你没有理由不能在你的代码中这样做,但至少要适度使用它,特别是如果它位于大型源文件中或其他人会查看你的代码时。
PyQt 设计是桥下的水。 我不确定这是不是最好的东西,但它可能受到 Qt 设计方式的影响。 AFAIK,Qt 历史上没有使用 C++ 命名空间(我不确定它现在是否使用它们),因此必须使用前缀。 但所有这些设计决策可能都发生在 10 多年前,现在应该不会影响您的设计决策。
我知道,如果我现在正在设计一个库,我肯定会选择使用 package 命名空间(您可以在 Python 中显式导入)而不是前缀。 假设我的前缀是 Pfx - 如果库用户不关心每次需要 function 时都写PfxFunc()
,他当然不会关心Pfx.Func()
中的额外字符,尤其是当他可以使用 import 时特定的符号名称以进一步缩短它。
考虑这种情况
from foo import *
from bar import *
x=baz()
现在假设foo
有一个名为baz()
的 function,我们在代码中使用它并且一切正常。 几个月或几年过去了, bar
的作者添加了一个名为baz()
的 function 。 有人更新了 egg ang bingo - 我们在程序中存在潜在的难以检测的错误。
更何况光看那三行代码,不去看看foo
和bar
就分不清baz
是从哪里来的
我唯一一次使用import *
是在解释器中保存一些输入
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.