Python * 导入
我通常被告知以下是不好的做法。
from module import *
主要原因(或者我被告知的)是,您可能会导入您不想要的东西,并且它可能会隐藏另一个模块中类似命名的函数或类。
然而,PyQt呢?
from PyQt4.QtCore import *
我见过的每个例子都是这样写的,主要是因为从Qt导出的所有内容都以“Q”开头,所以它不会隐藏任何东西。
共识是什么?使用 * 导入总是不好吗?
编辑:
需要明确的是,这个问题专门与使用 PyQt4 有关。这与我设计其他项目的方式无关。
基本上,我发现对 PEP8 进行编码提高了我的代码可读性,除了关于导入 PyQt4 的情况,所以直到现在我都忽略了纯粹主义者的不满。但现在我的开发小组正在决定一个约定,我想知道这是否是一种“实用性胜过纯粹性”的场景,或者我是否应该忍气吞声并处理巨大的 PyQt4 导入
from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......
I've generally been told that the following is bad practice.
from module import *
The main reasoning (or so I've been told), is that you could possibly import something you didn't want, and it could shadow a similarly named function or class from another module.
However, what about PyQt
from PyQt4.QtCore import *
Every example I've ever seen is written this way, mainly because everything exported from Qt starts with "Q", so it's not going to shadow anything.
What's the concensus? Is it always bad to use * imports?
EDIT:
Just to be clear, this question is specifically in regards to using PyQt4. It has nothing to do with the way I am designing some other project.
Basically, I've found that coding to PEP8 has improved my code readability, except with regards to importing PyQt4, and so I've disregarded the frowns from purists until now. But now my dev group is deciding on one convention and I'm wondering if this is a scenario "where practicality beats purity", or if I should just suck it up and deal with monstrous PyQt4 imports
from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这可能会变成一场宗教战争。这取决于您是否想要明确或是否想要避免过于冗长。一般来说,遵循Python之禅,最好是明确的,但是有时人们只是觉得列出特定模块的每个导入是不切实际的。
This can sort of turn into a religious war. It's a matter of whether you want to be explicit or whether you want to avoid being too verbose. In general, following the Zen of Python, it's better to be explicit, but sometimes people just don't find it practical to list every import from particular module.
我的一般规则是,如果我没有编写模块,我不会将其全部导入。我最担心的实际上是编写可能已在导入模块中定义的局部变量。因此,为了避免输入长模块名称,我使用 import as 功能。以您的模块为例,我将执行以下操作:
也就是说,我编写了许多支持模块,我将导入所有内容。与 pyqt 模块一样,我使用描述性名称来命名它们,以帮助显示它来自哪个模块。
按评论编辑
当我使用 import* 时,我的支持模块不包含类或任何可以创建新实例的内容。它们往往是仅修改现有实例的函数组。为了帮助澄清我的观点:如果我是源代码的所有者并且我将是主要维护者,我将使用 import* 否则我将使用 import as。
我使用导入作为功能的另一个原因是允许我模拟模块以进行调试。在我现在正在进行的一个项目中,我使用 pyVisa 与许多 GPIB 设备进行通信。当我未连接到设备 GPIB 网络时,我可以使用 dummy_visa 模块写入 stdout(以验证我发送的格式是否正确)并返回一个随机数(以测试我的应用程序)。见下文
My general rule is that if I didn't write the module, I don't import it all. My biggest fear is actually over writing local variables that might have been defined in the imported module. So to keep from having to type in long module names, I use the import as feature. Using your module as an example I would do the following:
That being said, I have many support modules that I write that I will import everything. Like the pyqt module, I name them with a descriptive name that helps show which module it came from.
Edit per comment
When I use import*, my support modules do not contain classes or anything that can create a new instance. They tend to be groups of functions that modify existing instances only. To help clarify my opinion: If I am the owner of the source code and I will be the primary maintainer, I will use the import* otherwise I would use the import as.
Another reason that I use the import as feature is to allow me to mock modules for debugging purposes. In a project that I am working on now, I use pyVisa to talk to a number of GPIB devices. When I'm not connected to the devices GPIB network, I can use a dummy_visa module to write to the stdout(to verify I am sending the correct format) and return a random number (to test my application). See below
对已经在命名约定中包含命名空间的模块(例如 PyQT 的 Q* )进行显式例外是完全合理的。但是,我建议明确默认设置仍然是“不要使用它”,并且只需在编码指南中列出此异常即可。
import *
当它用作应用程序中的命名空间操作技巧时也是可以接受的(我熟悉的两种形式是可选的 C 加速模块,它们在纯 Python 版本的末尾导入) ,并“扁平化”__init__
中的包命名空间)。关键是导入模块和被导入模块处于同一组开发人员的控制之下,因此避免命名空间冲突完全在他们的控制范围内。最后一个例外是为了方便交互式提示。
在其他情况下,最好导入特定名称或通过模块名称间接引用它们(或者,如果有一些常用引用项,则两者都执行:
import module # Can access everything
from module import a, b, c # 但是我们引用了很多,所以直接检索它们
Making an explicit exception for modules that already include a namespace in their naming convention (such as the
Q*
of PyQT) is perfectly reasonably. However, I recommend being clear that the default is still "don't use it" and simply list this exception in your coding guidelines.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 namespace in__init__
). The key point is that the importing module and the module being imported are under the control of the same set of developers, and hence avoiding namespace clashes is completely within their control.The final exception is for convenience at the interactive prompt.
In other situations, it is best to either import specific names or reference them indirectly through the module name (or, if there are some commonly reference items, do both:
import module # Can access anything
from module import a, b, c # But we reference these a lot, so retrieve them directly
教程,第 6 章:
教程,第 10 章:
所以看来有时这绝对是一个坏主意;大多数时候都不是最好的主意;在您想要减少输入的情况下(例如在交互式会话中),这是一个可接受的快捷方式。
Tutorial, chapter 6:
Tutorial, chapter 10:
So it seems that it is definitely a bad idea sometimes; not-the-best idea most of the time; and an acceptable shortcut in cases where you'd want to type less, eg in interactive sessions.
我发现
import *
被滥用,并且可能成为维护难题,因此我出于这个原因以及您所说的其他原因而避免使用它。也就是说,我觉得对于简短的交互式会话来说是可以的,例如from pylab import *
。在生产代码中,对于像
PyQt4.QtCore
这样您计划使用许多符号的包,我将使用以下语法之一,以明确符号来自哪个命名空间:I find
import *
gets abused, and can become a maintenance headache, so I avoid it for this and the other reasons you state. That said I feel it's okay for short interactive sessions, e.g.from pylab import *
.In production code, for packages like
PyQt4.QtCore
where you plan to use many of the symbols, I'd use one of the following syntaxes which make it explicit which namespace the symbols come from:一般来说,如果您要使用
from X import Y
,最好明确您要导入的内容。这不仅是因为它更安全,还因为它使您的代码更具可读性(并且升级到您正在使用的第三方模块不会有太大的可能意外破坏您的代码)。在一些演示大包的代码示例中,例如 Qt 或 matplotlib,这些示例将使用
from module import *
因为它们通常只从一个模块导入,这样可以节省输入并让示例代码到达重点。您没有理由不能在代码中执行此操作,但至少要适度使用它,尤其是在大型源文件中或其他人会查看您的代码时。In general, if you're going to use
from X import Y
, it's a good idea to be explicit about what you're importing. That's not just because it's safer, but also because it makes your code more readable (and upgrades to the third-party modules you're using won't have as much potential to incidentally break your code).In some code examples demonstrating big packages, like Qt or matplotlib, the examples will use
from module import *
because they're often only importing from one module, and it saves typing and lets their example code get to the point. There's no reason you can't do it in your code, but at least use it in moderation, especially if it's in big source files or other people will be looking at your code.PyQt 的设计已经过时了。我不确定这是最好的事情,但它可能受到 Qt 设计方式的影响。 AFAIK,Qt 历史上不使用 C++ 命名空间(我不确定它现在是否使用它们),因此必须使用前缀。但所有这些设计决策可能都发生在 10 多年前,这不应该影响您现在的设计决策。
我知道,如果我现在设计一个库,我肯定会选择使用包命名空间(您将在 Python 中显式导入)而不是前缀。假设我的前缀是 Pfx - 如果库用户不关心每次需要函数时都编写
PfxFunc()
,他当然不会关心Pfx.Func 中的额外字符()
,特别是当他可以使用带有特定符号名称的导入来进一步缩短它时。The PyQt design is water under the bridge. I'm not sure it's the best thing, but it's probably influenced by the way Qt was designed. AFAIK, Qt didn't use C++ namespaces historically (I'm not sure if it uses them now), and therefore had to use prefixes. But all of those design decisions probably happened more than 10 years ago, and that shouldn't affect your design decisions now.
I know that if I was designing a library now, I would definitely choose to use package namespaces (which you would import explicitly in Python) over prefixes. Let's say my prefix is Pfx - if the library user doesn't care writing
PfxFunc()
every time he needs a function, he certainly wouldn't care about the extra character inPfx.Func()
, especially when he can use import with specific symbol names to shorten that even more.考虑这种情况
现在假设
foo
有一个名为baz()
的函数,我们在代码中使用该函数,并且一切正常。几个月或几年过去了,bar
的作者添加了一个名为baz()
的函数。有人更新了 Egg ang Bingo - 我们的程序中可能存在难以检测的错误。更不用说光看这三行代码,如果不看
foo
和bar
我根本无法判断baz
来自哪里>我唯一一次使用
import *
是在解释器中以节省一些输入Consider this case
Now suppose
foo
has a function calledbaz()
that we are using in our code and everything is working fine. Months or years pass, the author ofbar
adds a function calledbaz()
. Someone updates the egg ang bingo - we have a potentially hard to detect bug in the program.Not to mention that just looking at those three lines of code, I can't tell where
baz
comes from without going and looking atfoo
andbar
The only time I'd use
import *
would be in the interpreter to save some typing