Python 导入的良好经验规则是什么?
我对在 Python 中导入模块的多种方式感到有点困惑。
import X
import X as Y
from A import B
我一直在阅读有关范围界定和命名空间的内容,但我想要一些关于什么是最佳策略、在什么情况下以及为什么的实用建议。 导入应该发生在模块级别还是方法/函数级别? 在 __init__.py
中还是在模块代码本身中?
我的问题并没有真正回答“Python包 - 按类导入,而不是文件< /a>”虽然它显然是相关的。
I am a little confused by the multitude of ways in which you can import modules in Python.
import X
import X as Y
from A import B
I have been reading up about scoping and namespaces, but I would like some practical advice on what is the best strategy, under which circumstances and why. Should imports happen at a module level or a method/function level? In the __init__.py
or in the module code itself?
My question is not really answered by "Python packages - import by class, not file" although it is obviously related.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
在我们公司的生产代码中,我们尝试遵循以下规则。
我们将导入放在文件的开头,就在主文件的文档字符串之后,例如:
现在,如果我们导入一个类,该类是导入模块中的少数几个之一,我们直接导入名称,这样在代码中我们只有使用最后一部分,例如:
但是,有些模块包含数十个类,例如所有可能的异常的列表。 然后我们导入模块本身并在代码中引用它:
我们尽可能少地使用 import X as Y,因为这使得搜索特定模块或类的使用变得困难。 然而,有时,如果您希望导入两个具有相同名称但存在于不同模块中的类,则必须使用它,例如:
作为一般规则,我们不会在方法内部进行导入 - 它们只会使代码变慢并且可读性较差。 有些人可能会发现这是轻松解决循环导入问题的好方法,但更好的解决方案是代码重组。
In production code in our company, we try to follow the following rules.
We place imports at the beginning of the file, right after the main file's docstring, e.g.:
Now, if we import a class that is one of few in the imported module, we import the name directly, so that in the code we only have to use the last part, e.g.:
There are modules, however, that contain dozens of classes, e.g. list of all possible exceptions. Then we import the module itself and reference to it in the code:
We use the
import X as Y
as rarely as possible, because it makes searching for usage of a particular module or class difficult. Sometimes, however, you have to use it if you wish to import two classes that have the same name, but exist in different modules, e.g.:As a general rule, we don't do imports inside methods -- they simply make code slower and less readable. Some may find this a good way to easily resolve cyclic imports problem, but a better solution is code reorganization.
让我粘贴由 Guido van Rossum 发起的 django-dev 邮件列表上的部分对话:
来源: http://groups.google。 com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
Let me just paste a part of conversation on django-dev mailing list started by Guido van Rossum:
Source: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
我通常会在模块级别使用
import X
。 如果您只需要模块中的单个对象,请使用from X import Y
。仅在遇到名称冲突时才使用
import X as Y
。当模块用作主模块时,我只在函数级别使用导入来导入我需要的东西,例如:
HTH
I would normally use
import X
on module level. If you only need a single object from a module, usefrom X import Y
.Only use
import X as Y
in case you're otherwise confronted with a name clash.I only use imports on function level to import stuff I need when the module is used as the main module, like:
HTH
上面有人说
相当于
import X
允许直接修改AP,而from X import ...
创建AP的副本。 对于from X import A..P
如果变量被修改,您不会获得变量的更新。 如果你修改它们,你只是修改了你的副本,但 X 确实知道你的修改。如果 AP 是函数,你就不会知道其中的区别。
Someone above said that
is equivalent to
import X
allows direct modifications to A-P, whilefrom X import ...
creates copies of A-P. Forfrom X import A..P
you do not get updates to variables if they are modified. If you modify them, you only modify your copy, but X does know about your modifications.If A-P are functions, you won't know the difference.
其他人已经涵盖了这里的大部分内容,但我只是想添加一种情况,当我尝试新版本的类或模块时,我将使用 import X as Y(暂时)。
因此,如果我们要迁移到模块的新实现,但不想一次性删除所有代码库,我们可能会编写一个
xyz_new
模块并在源文件中执行此操作我们已经迁移了:然后,一旦我们切换了整个代码库,我们只需用
xyz_new
替换xyz
模块,并将所有导入更改回Others have covered most of the ground here but I just wanted to add one case where I will use
import X as Y
(temporarily), when I'm trying out a new version of a class or module.So if we were migrating to a new implementation of a module, but didn't want to cut the code base over all at one time, we might write a
xyz_new
module and do this in the source files that we had migrated:Then, once we cut over the entire code base, we'd just replace the
xyz
module withxyz_new
and change all of the imports back to不要这样做:
除非你绝对确定你会使用该模块中的每一个东西。 即便如此,您可能应该重新考虑使用不同的方法。
除此之外,这只是风格问题。
很好,可以节省您大量的打字时间。 当我相当频繁地使用其中的某些内容时,我倾向于使用它。但是,如果您从该模块导入很多内容,则最终可能会得到如下所示的导入语句:
您明白了。 这就是进口之类的东西
变得有用的时候。 要么是这样,要么是我并没有经常使用 X 中的任何东西。
DON'T do this:
unless you are absolutely sure that you will use each and every thing in that module. And even then, you should probably reconsider using a different approach.
Other than that, it's just a matter of style.
is good and saves you lots of typing. I tend to use that when I'm using something in it fairly frequently But if you're importing a lot from that module, you could end up with an import statement that looks like this:
You get the idea. That's when imports like
become useful. Either that or if I'm not really using anything in X very frequently.
我通常尝试使用常规
import modulename
,除非模块名称很长,或者经常使用..例如,我会这样做..
..所以我可以做
soup = BSS( html)
而不是BeautifulSoup.BeautifulStoneSoup(html)
或者..
..当我只使用 XmppClientBase 时,而不是导入整个 xmpp
使用
import x as y 很方便。
假设我想运行 main( ) 函数来自另一个脚本,但我已经有一个 main() 函数..
..不会用 my_other_module 的
main
函数替换我的main
函数哦,有一件事 - 不要' t do
from x import *
- 这会让你的代码很难理解,因为你无法轻易地看到方法来自哪里 (from x import *; from y import *; my_func()
- my_func 在哪里定义?)在所有情况下,您可以只需执行
import modulename
然后执行modulename.subthing1.subthing2.method(" test")
...from x import y as z
的东西纯粹是为了方便 - 只要它能让你的代码更容易阅读或编写就可以使用它!I generally try to use the regular
import modulename
, unless the module name is long, or used often..For example, I would do..
..so I can do
soup = BSS(html)
instead ofBeautifulSoup.BeautifulStoneSoup(html)
Or..
..instead of importing the entire of xmpp when I only use the XmppClientBase
Using
import x as y
is handy if you want to import either very long method names , or to prevent clobbering an existing import/variable/class/method (something you should try to avoid completely, but it's not always possible)Say I want to run a main() function from another script, but I already have a main() function..
..wouldn't replace my
main
function with my_other_module'smain
Oh, one thing - don't do
from x import *
- it makes your code very hard to understand, as you cannot easily see where a method came from (from x import *; from y import *; my_func()
- where is my_func defined?)In all cases, you could just do
import modulename
and then domodulename.subthing1.subthing2.method("test")
...The
from x import y as z
stuff is purely for convenience - use it whenever it'll make your code easier to read or write!当你有一个编写良好的库时(Python 中有时会出现这种情况),你应该导入它并按原样使用它。 编写良好的库往往具有自己的生命和语言,从而产生令人愉悦的代码,而您很少引用该库。 当一个库编写得很好时,您不应该需要经常重命名或进行其他任何操作。
有时不可能这样写,或者你想从导入的库中删除一些东西。
有时您会为很多事情执行此操作,如果您的导入字符串溢出 80 列,那么这样做是个好主意:
最好的策略是将所有这些导入保留在文件的顶部。 最好按字母顺序排列,首先是 import 语句,然后是 from import 语句。
现在我告诉你为什么这是最好的大会。
Python 完全可以有一个自动导入,当无法从全局命名空间中找到该值时,它会从主导入中查找该值。 但这不是一个好主意。 我简短地解释一下原因。 除了实现起来比简单导入更复杂之外,程序员不会过多地考虑依赖关系,也不会用其他方式找出导入内容,而不仅仅是查看导入。
需要找出依赖关系是人们讨厌“from ... import *”的原因之一。 不过,存在一些需要执行此操作的不良示例,例如 opengl -wrappings。
因此,导入定义对于定义程序的依赖关系实际上很有价值。 这就是你应该如何利用它们的方式。 从它们中你可以快速检查一些奇怪的函数是从哪里导入的。
When you have a well-written library, which is sometimes case in python, you ought just import it and use it as it. Well-written library tends to take life and language of its own, resulting in pleasant-to-read -code, where you rarely reference the library. When a library is well-written, you ought not need renaming or anything else too often.
Sometimes it's not possible to write it this way, or then you want to lift down things from library you imported.
Sometimes you do this for lot of things, if your import string overflows 80 columns, It's good idea to do this:
The best strategy is to keep all of these imports on the top of the file. Preferrably ordered alphabetically, import -statements first, then from import -statements.
Now I tell you why this is the best convention.
Python could perfectly have had an automatic import, which'd look from the main imports for the value when it can't be found from global namespace. But this is not a good idea. I explain shortly why. Aside it being more complicated to implement than simple import, programmers wouldn't be so much thinking about the depedencies and finding out from where you imported things ought be done some other way than just looking into imports.
Need to find out depedencies is one reason why people hate "from ... import *". Some bad examples where you need to do this exist though, for example opengl -wrappings.
So the import definitions are actually valuable as defining the depedencies of the program. It is the way how you should exploit them. From them you can quickly just check where some weird function is imported from.
如果您对同一模块/类有不同的实现,则
import X as Y
非常有用。通过一些嵌套的
try..import.. except ImportError..import
,您可以在代码中隐藏实现。 请参阅 lxml etree 导入示例:The
import X as Y
is useful if you have different implementations of the same module/class.With some nested
try..import..except ImportError..import
s you can hide the implementation from your code. See lxml etree import example:我和杰森在一起,事实上没有使用
但就我而言(我不是专家程序员,所以我的代码不太符合编码风格)我通常在我的程序中创建一个包含所有常量的文件,例如program版本、作者、错误消息和所有这些东西,所以文件只是定义,然后我进行导入,
这节省了我很多时间。 但它是唯一具有该导入的文件,这是因为该文件内的所有内容都只是变量声明。
在包含类和定义的文件中进行这种导入可能很有用,但是当您必须阅读该代码时,您会花费大量时间来查找函数和类。
I'm with Jason in the fact of not using
But in my case (i'm not an expert programmer, so my code does not meet the coding style too well) I usually do in my programs a file with all the constants like program version, authors, error messages and all that stuff, so the file are just definitions, then I make the import
That saves me a lot of time. But it's the only file that has that import, and it's because all inside that file are just variable declarations.
Doing that kind of import in a file with classes and definitions might be useful, but when you have to read that code you spend lots of time locating functions and classes.