使用“导入模块”仍是“从模块导入”?

我试图找到一个综合指南,以了解最好是使用import module仍是from module import ? 我刚开始使用Python,而且正在尝试着眼于最佳实践。 html

基本上,我但愿有人能分享他们的经验,其余开发人员有什么喜爱,以及避免未来遇到麻烦的最佳方法是什么? python


#1楼

我刚刚发现了这两种方法之间的另外一个细微差异。 app

若是模块foo使用如下导入: python2.7

from itertools import count

而后,模块bar可能会错误地使用count就像它是在foo中定义的同样,而不是在itertools定义的: ide

import foo
foo.count()

若是foo使用: 函数

import itertools

该错误仍然可能,但不太可能发生。 bar须要: 测试

import foo
foo.itertools.count()

这给我带来了麻烦。 我有一个模块,该模块错误地从一个未定义异常的模块中导入了一个异常,仅从其余模块中导入了该异常( from module import SomeException )。 当再也不须要导入并将其删除时,有问题的模块将被破坏。 spa


#2楼

这里还有另外一个细节,未说起,与写入模块有关。 固然,这可能不是很常见,可是我不时须要它。 code

因为引用和名称绑定在Python中的工做方式,若是您想从模块外部更新模块中的某些符号(例如foo.bar),并更改其余导入代码“ see”,则必须导入foo某种方式。 例如: htm

模块foo:

bar = "apples"

模块a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

模块b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

可是,若是导入符号名称而不是模块名称,则将没法使用。

例如,若是我在模块a中这样作:

from foo import bar
bar = "oranges"

a以外的任何代码都不会将bar视为“橙色”,由于我对bar的设置仅影响模块a中的名称“ bar”,它没有“进入” foo模块对象并更新其“ bar”。


#3楼

这是另外一个未说起的区别。 这是从http://docs.python.org/2/tutorial/modules.html逐字复制的

请注意,使用时

from package import item

该项目能够是包的子模块(或子包),也能够是包中定义的其余名称,例如函数,类或变量。 import语句首先测试项目是否在包装中定义; 若是不是,则假定它是一个模块并尝试加载它。 若是找不到它,则会引起ImportError异常。

相反,当使用相似

import item.subitem.subsubitem

除最后一个项目外,每一个项目都必须是一个包装; 最后一项能够是模块或包,但不能是上一项中定义的类或函数或变量。


#4楼

即便许多人已经解释了import import from ,我仍是想尝试多解释一下幕后发生的事情以及它发生的全部变化。


import foo

导入foo ,并在当前名称空间中建立对该模块的引用。 而后,您须要定义完整的模块路径,以从模块内部访问特定的属性或方法。

例如foo.bar但不是bar

from foo import bar

导入foo ,并建立对列出的全部成员的引用( bar )。 不设置变量foo

例如bar但不是bazfoo.baz

from foo import *

导入foo ,并建立对该模块在当前名称空间中定义的全部公共对象的引用(若是存在__all__ ,则在__all__列出的全部内容,不然全部不以_开头的内容)。 不设置变量foo

例如barbaz但不是_quxfoo._qux


如今让咱们看看什么时候import XY

>>> import sys
>>> import os.path

检查名称为osos.path sys.modules

>>> 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'>

使用osos.path检查globals()locals()命名空间字典:

>>> 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'
>>>

从以上示例中,咱们发现仅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'>
 >>>

但不是path

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

一旦从locals()命名空间中删除os ,就没法访​​问osos.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
>>>

如今让咱们来谈谈import from

from

>>> import sys
>>> from os import path

使用osos.path检查sys.modules

>>> 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'>

咱们发如今sys.modules咱们使用import name发现了与以前相同的结果

OK,让咱们检查一下它在locals()globals()命名空间字典中的外观:

>>> 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'
>>>

您可使用名称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
>>>

让咱们从locals()删除'path':

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

最后一个使用别名的示例:

>>> 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'>
>>>

并且没有定义路径:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

#5楼

import package
import module

使用import ,令牌必须是模块(包含Python命令的文件)或包( sys.path包含文件__init__.py的文件夹)。

有子包时:

import package1.package2.package
import package1.package2.module

文件夹(包)或文件(模块)的要求相同,可是文件夹或文件必须在package2内,而package2必须在package1 ,并且package1package2必须包含__init__.py文件。 https://docs.python.org/2/tutorial/modules.html

from导入样式:

from package1.package2 import package
from package1.package2 import module

程序包或模块输入包含import语句的文件的名称空间做为module (或package )而不是package1.package2.module 。 您始终能够绑定到更方便的名称:

a = big_package_name.subpackage.even_longer_subpackage_name.function

只有from导入样式容许您命名特定的函数或变量:

from package3.module import some_function

被容许,可是

import package3.module.some_function

不容许。

相关文章
相关标签/搜索