我試圖找到一個綜合指南,以瞭解最好是使用import module
仍是from module import
? 我剛開始使用Python,而且正在嘗試着眼於最佳實踐。 html
基本上,我但願有人能分享他們的經驗,其餘開發人員有什麼喜愛,以及避免未來遇到麻煩的最佳方法是什麼? python
我剛剛發現了這兩種方法之間的另外一個細微差異。 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
這裏還有另外一個細節,未說起,與寫入模塊有關。 固然,這可能不是很常見,可是我不時須要它。 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」。
這是另外一個未說起的區別。 這是從http://docs.python.org/2/tutorial/modules.html逐字複製的
請注意,使用時
from package import item
該項目能夠是包的子模塊(或子包),也能夠是包中定義的其餘名稱,例如函數,類或變量。 import語句首先測試項目是否在包裝中定義; 若是不是,則假定它是一個模塊並嘗試加載它。 若是找不到它,則會引起ImportError異常。
相反,當使用相似
import item.subitem.subsubitem
除最後一個項目外,每一個項目都必須是一個包裝; 最後一項能夠是模塊或包,但不能是上一項中定義的類或函數或變量。
即便許多人已經解釋了import
import from
,我仍是想嘗試多解釋一下幕後發生的事情以及它發生的全部變化。
import foo
: 導入foo
,並在當前名稱空間中建立對該模塊的引用。 而後,您須要定義完整的模塊路徑,以從模塊內部訪問特定的屬性或方法。
例如foo.bar
但不是bar
from foo import bar
: 導入foo
,並建立對列出的全部成員的引用( bar
)。 不設置變量foo
。
例如bar
但不是baz
或foo.baz
from foo import *
: 導入foo
,並建立對該模塊在當前名稱空間中定義的全部公共對象的引用(若是存在__all__
,則在__all__
列出的全部內容,不然全部不以_
開頭的內容)。 不設置變量foo
。
例如bar
和baz
但不是_qux
或foo._qux
。
如今讓咱們看看什麼時候import XY
:
>>> import sys >>> import os.path
檢查名稱爲os
和os.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'>
使用os
和os.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
,就沒法訪問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 >>>
import from
: from
: >>> import sys >>> from os import path
os
和os.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' >>>
import package import module
使用import
,令牌必須是模塊(包含Python命令的文件)或包( sys.path
包含文件__init__.py
的文件夾)。
有子包時:
import package1.package2.package import package1.package2.module
文件夾(包)或文件(模塊)的要求相同,可是文件夾或文件必須在package2
內,而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
程序包或模塊輸入包含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
不容許。