简体   繁体   English

Python * 进口

[英]Python * imports

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.主要原因(或者我被告知)是您可能会导入您不想要的东西,并且它可能会影响另一个模块中类似名称的 function 或 class 。

However, what about PyQt但是,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.我见过的每个示例都是这样编写的,主要是因为从 Qt 导出的所有内容都以“Q”开头,因此不会影响任何内容。

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.为了清楚起见,这个问题专门针对使用 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.基本上,我发现 PEP8 编码提高了我的代码可读性,除了导入 PyQt4 方面,所以直到现在我都没有理会纯粹主义者的皱眉。 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但是现在我的开发组正在决定一个约定,我想知道这是否是“实用性胜过纯度”的场景,或者我是否应该接受它并处理可怕的 PyQt4 导入

from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......

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.一般来说,遵循Python 的 Zen ,最好是明确的,但有时人们只是觉得列出来自特定模块的每个导入并不实用。

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.因此,为了避免输入长模块名称,我使用 import as 功能。 Using your module as an example I would do the following:以您的模块为例,我将执行以下操作:

import PyQt4.QtCore as qt

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.就像 pyqt 模块一样,我用一个描述性的名称来命名它们,这有助于显示它来自哪个模块。

Edit per comment按评论编辑
When I use import*, my support modules do not contain classes or anything that can create a new instance.当我使用 import* 时,我的支持模块不包含类或任何可以创建新实例的东西。 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.为了帮助澄清我的观点:如果我是源代码的所有者并且我将是主要维护者,我将使用 import* 否则我将使用 import as。

Another reason that I use the import as feature is to allow me to mock modules for debugging purposes.我使用 import as 功能的另一个原因是允许我模拟模块以进行调试。 In a project that I am working on now, I use pyVisa to talk to a number of GPIB devices.在我现在正在进行的一个项目中,我使用 pyVisa 与许多 GPIB 设备进行通信。 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).当我没有连接到设备 GPIB 网络时,我可以使用 dummy_visa 模块写入标准输出(以验证我发送的格式正确)并返回一个随机数(以测试我的应用程序)。 See below见下文

if visa_debug:
    import dummy_visa as visa
else:
    import visa
gpib = visa.Instrument("GPIB0::10")
gpib.write("MEAS:VOLT?")

Making an explicit exception for modules that already include a namespace in their naming convention (such as the Q* of PyQT) is perfectly reasonably.对已经在命名约定中包含命名空间的模块(例如 PyQT 的Q* )进行显式例外是完全合理的。 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__ ). 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__中的命名空间)。 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 import module # Can access any from module import a, b, c # 但是我们引用了很多,所以直接检索

Tutorial, chapter 6 :教程,第 6 章

Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code.请注意,通常不赞成从模块或 package 导入 * 的做法,因为它通常会导致代码可读性差。 However, it is okay to use it to save typing in interactive sessions.但是,可以使用它来节省交互式会话中的输入。

Tutorial, chapter 10 :教程,第 10 章

Be sure to use the import os style instead of from os import *.请务必使用 import os 样式而不是 from os import *。 This will keep os.open() from shadowing the built-in open() function which operates much differently.这将使 os.open() 不会遮蔽内置的 open() function,后者的操作方式大不相同。

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.并且在您想要减少输入的情况下(例如在交互式会话中)是一个可接受的快捷方式。

I find import * gets abused, and can become a maintenance headache, so I avoid it for this and the other reasons you state.我发现import *被滥用了,并且可能成为维护方面的难题,所以我避免使用它,因为这个原因以及 state 的其他原因。 That said I feel it's okay for short interactive sessions, eg from pylab import * .也就是说,我觉得简短的交互式会话没问题,例如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:在生产代码中,对于像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()

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.一般来说,如果您要使用from X import Y ,最好明确说明您要导入的内容。 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.在一些演示大包的代码示例中,例如 Qt 或 matplotlib,这些示例将使用from module import *因为它们通常只从一个模块导入,这样可以节省键入并让示例代码切入主题。 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.你没有理由不能在你的代码中这样做,但至少要适度使用它,特别是如果它位于大型源文件中或其他人会查看你的代码时。

The PyQt design is water under the bridge. PyQt 设计是桥下的水。 I'm not sure it's the best thing, but it's probably influenced by the way Qt was designed.我不确定这是不是最好的东西,但它可能受到 Qt 设计方式的影响。 AFAIK, Qt didn't use C++ namespaces historically (I'm not sure if it uses them now), and therefore had to use prefixes. AFAIK,Qt 历史上没有使用 C++ 命名空间(我不确定它现在是否使用它们),因此必须使用前缀。 But all of those design decisions probably happened more than 10 years ago, and that shouldn't affect your design decisions now .但所有这些设计决策可能都发生在 10 多年前,现在应该不会影响您的设计决策。

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.我知道,如果我现在正在设计一个库,我肯定会选择使用 package 命名空间(您可以在 Python 中显式导入)而不是前缀。 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 in Pfx.Func() , especially when he can use import with specific symbol names to shorten that even more.假设我的前缀是 Pfx - 如果库用户不关心每次需要 function 时都写PfxFunc() ,他当然不会关心Pfx.Func()中的额外字符,尤其是当他可以使用 import 时特定的符号名称以进一步缩短它。

Consider this case考虑这种情况

from foo import *
from bar import *

x=baz()

Now suppose foo has a function called baz() that we are using in our code and everything is working fine.现在假设foo有一个名为baz()的 function,我们在代码中使用它并且一切正常。 Months or years pass, the author of bar adds a function called baz() .几个月或几年过去了, bar的作者添加了一个名为baz()的 function 。 Someone updates the egg ang bingo - we have a potentially hard to detect bug in the program.有人更新了 egg ang bingo - 我们在程序中存在潜在的难以检测的错误。

Not to mention that just looking at those three lines of code, I can't tell where baz comes from without going and looking at foo and bar更何况光看那三行代码,不去看看foobar就分不清baz是从哪里来的

The only time I'd use import * would be in the interpreter to save some typing我唯一一次使用import *是在解释器中保存一些输入

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM