使用「導入模塊」仍是「從模塊導入」?

我試圖找到一個綜合指南,以瞭解最好是使用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

不容許。

相關文章
相關標籤/搜索