Fil*_*vić 370 python python-import
我试图找到一个关于是否最好使用的综合指南import module或from module import?我刚刚开始使用Python,我试图从最初的实践开始.
基本上,我希望如果有人能分享他们的经验,有什么喜好其他开发商,什么是避免任何的最好办法陷阱的道路?
Mar*_*ddy 426
import module和之间的区别from module import foo主要是主观的.选择你最喜欢的那个,并在使用它时保持一致.以下是一些可以帮助您做出决定的要点.
import module
import陈述的维护.不需要添加任何其他导入即可开始使用模块中的其他项目module.foo您的代码可能是乏味和冗余的(通过使用import module as mo然后键入可以最小化乏味mo.foo)from module import foo
fooimport语句foo.例如,与之ceil()相比,它不太清楚math.ceil()这两种方法都可以接受,但不要使用from module import *.
对于任何合理的大量代码,如果您import *将可能将其粘合到模块中,则无法将其删除.这是因为很难确定代码中使用的项目来自"模块",这使得很容易达到您认为不再使用import它的程度,但是很难确定.
Mic*_*ett 127
这里有另一个细节,未提及,与写入模块有关.虽然这可能不是很常见,但我不时需要它.
由于引用和名称绑定在Python中的工作方式,如果你想更新模块中的某些符号,比如foo.bar,从该模块外部更新,并让其他导入代码"看到"更改,你必须导入foo a某种方式.例如:
模块foo:
bar = "apples"
Run Code Online (Sandbox Code Playgroud)
模块a:
import foo
foo.bar = "oranges" # update bar inside foo module object
Run Code Online (Sandbox Code Playgroud)
模块b:
import foo
print foo.bar # if executed after a's "foo.bar" assignment, will print "oranges"
Run Code Online (Sandbox Code Playgroud)
但是,如果导入符号名称而不是模块名称,则不起作用.
例如,如果我在模块a中执行此操作:
from foo import bar
bar = "oranges"
Run Code Online (Sandbox Code Playgroud)
在a之外没有代码会看到bar为"oranges",因为我的bar设置只影响了模块a中的名称"bar",它没有"到达"foo模块对象并更新其"bar".
Jam*_*pam 71
虽然很多人已经解释过importvs import from,但是我想尝试更多地解释一下在幕后发生的事情,以及它所改变的所有地方.
import foo:导入foo,并在当前名称空间中创建对该模块的引用.然后,您需要定义已完成的模块路径以从模块内部访问特定属性或方法.
例如,foo.bar但不bar
from foo import bar:导入foo并创建对列出的所有成员的引用(bar).不设置变量foo.
例如bar但不是baz或foo.baz
from foo import *:导入foo,并创建对当前命名空间中该模块定义的所有公共对象的引用(__all__if __all__exists中列出的所有内容,否则不是以所有内容开头_).不设置变量foo.
如bar和baz而不是_qux或foo._qux.
现在让我们看看我们做什么import X.Y:
>>> import sys
>>> import os.path
Run Code Online (Sandbox Code Playgroud)
检查sys.modules姓名os和os.path:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Run Code Online (Sandbox Code Playgroud)
使用和检查globals()和locals()命名空间dicts :osos.path
>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>
Run Code Online (Sandbox Code Playgroud)
从上面的例子中我们发现只os插入了本地和全局命名空间.所以,我们应该可以使用:
>>> os
<module 'os' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
Run Code Online (Sandbox Code Playgroud)
但不是path.
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Run Code Online (Sandbox Code Playgroud)
一旦你删除os从当地人()命名空间,您将无法访问os,以及os.path即使他们在sys.modules中存在:
>>> del locals()['os']
>>> os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Run Code Online (Sandbox Code Playgroud)
import from:from:>>> import sys
>>> from os import path
Run Code Online (Sandbox Code Playgroud)
sys.modules与os和os.path:>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Run Code Online (Sandbox Code Playgroud)
我们发现在sys.modules我们发现与之前使用的相同import name
好吧,让我们看看它locals()和globals()命名空间dicts中的样子:
>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>
Run Code Online (Sandbox Code Playgroud)
您可以使用名称path而不是os.path:
>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Run Code Online (Sandbox Code Playgroud)
让我们删除'path' locals():
>>> del locals()['path']
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Run Code Online (Sandbox Code Playgroud)
使用别名的最后一个示例:
>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
Run Code Online (Sandbox Code Playgroud)
并没有定义路径:
>>> globals()['path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
Run Code Online (Sandbox Code Playgroud)
dwc*_*dwc 39
支持这两种方式的原因是:有时候一种方式比另一种方式更合适.
import module:当您使用模块中的许多位时很好.缺点是您需要使用模块名称限定每个引用.
from module import ...:很好,导入的项目可以直接使用,没有模块名称前缀.缺点是你必须列出你使用的每一件事,并且在代码中不清楚某些东西来自何处.
使用哪个取决于哪个使代码清晰可读,并且与个人偏好有很多关系.我倾向于import module普遍,因为在代码中,对象或函数的来源非常清楚.我用from module import ...的时候我使用了一些对象/功能一个不少的代码.
Ste*_*ini 34
我个人经常使用
from package.subpackage.subsubpackage import module
Run Code Online (Sandbox Code Playgroud)
然后访问所有内容
module.function
module.modulevar
Run Code Online (Sandbox Code Playgroud)
原因是同时你有很短的调用,并且你清楚地定义了每个例程的模块名称空间,如果你必须在源代码中搜索给定模块的使用,这是非常有用的.
不用说,不要使用import*,因为它会污染你的命名空间,它不会告诉你给定函数的来源(来自哪个模块)
当然,如果两个不同的软件包中有两个不同模块的模块名称相同,则可能会遇到麻烦
from package1.subpackage import module
from package2.subpackage import module
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当然你会遇到麻烦,但是有一个强烈暗示你的包装布局存在缺陷,你必须重新考虑它.
And*_*are 15
import module
Run Code Online (Sandbox Code Playgroud)
最好何时使用模块中的许多功能.
from module import function
Run Code Online (Sandbox Code Playgroud)
当您只想要避免使用模块中的所有函数和类型来污染全局命名空间时,最好function.
我刚刚发现了这两种方法之间的另一个细微差别.
如果模块foo使用以下导入:
from itertools import count
Run Code Online (Sandbox Code Playgroud)
然后模块bar可能会错误地使用,count就像它被定义foo,而不是在itertools:
import foo
foo.count()
Run Code Online (Sandbox Code Playgroud)
如果foo使用:
import itertools
Run Code Online (Sandbox Code Playgroud)
错误仍然存在,但不太可能发生.bar需要:
import foo
foo.itertools.count()
Run Code Online (Sandbox Code Playgroud)
这给我带来了一些麻烦.我有一个模块,错误地从没有定义它的模块导入异常,只从其他模块导入它(使用from module import SomeException).当不再需要和删除导入时,违规模块被破坏.
小智 9
这是另一个未提及的差异.这是从http://docs.python.org/2/tutorial/modules.html逐字复制的
请注意,使用时
from package import item
Run Code Online (Sandbox Code Playgroud)
该项可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量.import语句首先测试是否在包中定义了该项; 如果没有,它假定它是一个模块并尝试加载它.如果找不到它,则引发ImportError异常.
相反,使用语法时
import item.subitem.subsubitem
Run Code Online (Sandbox Code Playgroud)
每个项目除了最后一个必须是一个包; 最后一项可以是模块或包,但不能是前一项中定义的类或函数或变量.
我想补充一下。如果遇到循环导入,了解 Python 如何将导入的模块作为属性处理会很有用。
我有以下结构:
mod/
__init__.py
main.py
a.py
b.py
c.py
d.py
Run Code Online (Sandbox Code Playgroud)
从 main.py 我将使用不同的导入方法导入其他模块
主要.py:
import mod.a
import mod.b as b
from mod import c
import d
Run Code Online (Sandbox Code Playgroud)
dis.dis 显示差异(注意模块名称,abcd):
1 0 LOAD_CONST 0 (-1)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (mod.a)
9 STORE_NAME 1 (mod)
2 12 LOAD_CONST 0 (-1)
15 LOAD_CONST 1 (None)
18 IMPORT_NAME 2 (b)
21 STORE_NAME 2 (b)
3 24 LOAD_CONST 0 (-1)
27 LOAD_CONST 2 (('c',))
30 IMPORT_NAME 1 (mod)
33 IMPORT_FROM 3 (c)
36 STORE_NAME 3 (c)
39 POP_TOP
4 40 LOAD_CONST 0 (-1)
43 LOAD_CONST 1 (None)
46 IMPORT_NAME 4 (mod.d)
49 LOAD_ATTR 5 (d)
52 STORE_NAME 5 (d)
55 LOAD_CONST 1 (None)
Run Code Online (Sandbox Code Playgroud)
最后它们看起来是一样的(STORE_NAME 是每个示例中的结果),但如果您需要考虑以下四个循环导入,则值得注意:
foo/
__init__.py
a.py
b.py
Run Code Online (Sandbox Code Playgroud)
a.py:
import foo.b
Run Code Online (Sandbox Code Playgroud)
b.py:
import foo.a
Run Code Online (Sandbox Code Playgroud)
>>> import foo.a
>>>
Run Code Online (Sandbox Code Playgroud)
这有效
bar/
__init__.py
a.py
b.py
Run Code Online (Sandbox Code Playgroud)
a.py:
import bar.b as b
Run Code Online (Sandbox Code Playgroud)
b.py:
import bar.a as a
Run Code Online (Sandbox Code Playgroud)
>>> import bar.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bar\a.py", line 1, in <module>
import bar.b as b
File "bar\b.py", line 1, in <module>
import bar.a as a
AttributeError: 'module' object has no attribute 'a'
Run Code Online (Sandbox Code Playgroud)
没有骰子
baz/
__init__.py
a.py
b.py
Run Code Online (Sandbox Code Playgroud)
a.py:
from baz import b
Run Code Online (Sandbox Code Playgroud)
b.py:
from baz import a
Run Code Online (Sandbox Code Playgroud)
>>> import baz.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "baz\a.py", line 1, in <module>
from baz import b
File "baz\b.py", line 1, in <module>
from baz import a
ImportError: cannot import name a
Run Code Online (Sandbox Code Playgroud)
类似的问题...但显然 from x import y 与 import import xy as y 不同
qux/
__init__.py
a.py
b.py
Run Code Online (Sandbox Code Playgroud)
a.py:
import b
Run Code Online (Sandbox Code Playgroud)
b.py:
import a
Run Code Online (Sandbox Code Playgroud)
>>> import qux.a
>>>
Run Code Online (Sandbox Code Playgroud)
这个也可以用
import package
import module
Run Code Online (Sandbox Code Playgroud)
使用import,令牌必须是模块(包含Python命令的文件)或包(sys.path包含文件的文件夹__init__.py)。
有子包时:
import package1.package2.package
import package1.package2.module
Run Code Online (Sandbox Code Playgroud)
为文件夹(封装)或文件(模块)的要求是相同的,但该文件夹或文件必须是内部package2必须是内部package1,并且两个package1和package2必须包含__init__.py文件。https://docs.python.org/2/tutorial/modules.html
具有from导入样式:
from package1.package2 import package
from package1.package2 import module
Run Code Online (Sandbox Code Playgroud)
程序包或模块将输入包含import语句的文件的名称空间用module(或package)代替package1.package2.module。您始终可以绑定到更方便的名称:
a = big_package_name.subpackage.even_longer_subpackage_name.function
Run Code Online (Sandbox Code Playgroud)
只有from导入样式允许您命名特定的函数或变量:
from package3.module import some_function
Run Code Online (Sandbox Code Playgroud)
被允许,但是
import package3.module.some_function
Run Code Online (Sandbox Code Playgroud)
不允许。
由于我还是初学者,因此我将尝试以一种简单的方式来解释这一点:在Python中,我们有三种类型的import语句,它们是:
1.通用进口:
import math
Run Code Online (Sandbox Code Playgroud)
这种类型的导入是我个人的最爱,这种导入技术的唯一缺点是,如果需要使用任何模块的功能,则必须使用以下语法:
math.sqrt(4)
Run Code Online (Sandbox Code Playgroud)
当然,它会增加打字的工作量,但是作为一个初学者,它将帮助您跟踪与之相关的模块和功能(一个好的文本编辑器会大大减少打字的工作量,建议使用)。
使用以下import语句可以进一步减少打字工作:
import math as m
Run Code Online (Sandbox Code Playgroud)
现在,math.sqrt()可以使用代替使用m.sqrt()。
2.函数导入:
from math import sqrt
Run Code Online (Sandbox Code Playgroud)
如果您的代码只需要访问模块中的单个或几个函数,而要使用模块中的任何新项,则必须更新import语句,则这种类型的导入最适合。
3.普遍进口:
from math import *
Run Code Online (Sandbox Code Playgroud)
尽管它可以显着减少键入工作,但不建议这样做,因为它将用模块中的各种函数填充代码,并且它们的名称可能与用户定义函数的名称冲突。 例:
这是我当前目录的目录结构:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\n. \n\xe2\x94\x94\xe2\x94\x80a \n \xe2\x94\x94\xe2\x94\x80b \n \xe2\x94\x94\xe2\x94\x80c\n
该import语句会记住所有中间名称。
\n这些名称必须经过限定:
In[1]: import a.b.c\n\nIn[2]: a\nOut[2]: <module 'a' (namespace)>\n\nIn[3]: a.b\nOut[3]: <module 'a.b' (namespace)>\n\nIn[4]: a.b.c\nOut[4]: <module 'a.b.c' (namespace)>\nRun Code Online (Sandbox Code Playgroud)该from ... import ...语句仅记住导入的名称。
\n此名称不得被限定:
In[1]: from a.b import c\n\nIn[2]: a\nNameError: name 'a' is not defined\n\nIn[2]: a.b\nNameError: name 'a' is not defined\n\nIn[3]: a.b.c\nNameError: name 'a' is not defined\n\nIn[4]: c\nOut[4]: <module 'a.b.c' (namespace)>\nRun Code Online (Sandbox Code Playgroud)