Python import與from import使用和區別解讀
系統自帶模塊(庫)
```cpp import re target = 'abc1234xyz' re.search('(\d+)', target)
但有時候,你可能會看到某些人這樣寫代碼: ```python from re import search target = 'abc1234xyz' search('(\d+)', target)
那麼這兩種導入方式有什麼區別呢?
我們分別使用type函數來看看他們的類型:
>>> import re >>> type(re) <class 'module'> >>> from re import search >>> type(search) <class 'function'>
可以看到,直接使用import re導入的re它是一個module類,也就是模塊。我們把它成為正則表達式模塊。而當我們from re import search時,這個search是一個function類,我們稱呼它為search 函數。
一個模塊裡面可以包含多個函數。
如果在你的代碼裡面,你已經確定隻使用search函數,不會再使用正則表達式裡面的其他函數瞭,那麼你使用兩種方法都可以,沒什麼區別。
但是,如果你要使用正則表達式下面的多個函數,或者是一些常量,那麼用第一種方案會更加簡潔清晰。
例如:
import re re.search('c(.*?)x', flags=re.S) re.sub('[a-zA-Z0-9]', '***', target, flags=re.I)
在這個例子中,你分別使用瞭re.search,re.sub,re.S和re.I。後兩者是常量,用於忽略換行符和大小寫。
但是,如果你使用from re import search, sub, S, I來寫代碼,那麼代碼就會變成這樣:
import re search('c(.*?)x', flags=S) sub('[a-zA-Z0-9]', '***', target, flags=I)
看起來雖然簡潔瞭,但是,一旦你的代碼行數多瞭以後,你很容易忘記S和I這兩個變量是什麼東西。而且我們自己定義的函數,也很有可能取名為sub或者search,從而覆蓋正則表達式模塊下面的這兩個同名函數。這就會導致很多難以覺察的潛在 bug。
再舉一個例子。Python 的 datetime模塊,我們可以直接import datetime,此時我們導入的是一個datetime模塊,
輸出為:class‘module'
但是如果你寫為from datetime import datetime,那麼你導入的datetime是一個type類:
輸出為:class‘type'
因為這種方式導入的datetime,它就是Python 中的一種類型,用於表示包含日期和時間的數據。
這兩種導入方式導入的datetime,雖然名字一樣,但是他們的意義完全不一樣,請大傢觀察下面兩種寫法:
import datetime now = datetime.datetime.now() one_hour_ago = now - datetime.timedelta(hours=1) from datetime import datetime, timedelta now = datetime.now() one_hour_ago = now - timedelta(hours=1)
第二種寫法看似簡單,但實則改動起來卻更為麻煩。例如我還需要增加一個變量today用於記錄今日的日期。
對於第一段代碼,我們隻需要增加一行即可:
today = datetime.date.today()
但對於第二行來說,我們需要首先修改導入部分的代碼:
from datetime import datetime, timedelta, date
然後才能改代碼:today = date.today()
這樣一來你就要修改兩個地方,反倒增加瞭負擔。
第三方庫
在使用某些第三方庫的代碼裡面,我們會看到類似這樣的寫法:
from lxml.html import fromstring
selector = fromstring(HTML)
但是我們還可以寫為:
from lxml import html
selector = html.fromstring(HTML)
但是,下面這種寫法會導致報錯:
import lxml
selector = lxml.html.fromstring(HTML)
那麼這裡的lxml.html又是什麼東西呢?
這種情況多常見於一些特別大型的第三方庫中,這種庫能處理多種類型的數據。例如lxml它既能處理xml的數據,又能處理html的數據,於是這種庫會劃分子模塊,lxml.html模塊專門負責html相關的數據。
動手試試
在使用某些第三方庫的代碼裡面,我們會看到類似這樣的寫法:
from lxml.html import fromstring selector = fromstring(HTML)
但是我們還可以寫為:
from lxml import html selector = html.fromstring(HTML)
但是,下面這種寫法會導致報錯:
import lxml selector = lxml.html.fromstring(HTML)
那麼這裡的lxml.html又是什麼東西呢?
這種情況多常見於一些特別大型的第三方庫中,這種庫能處理多種類型的數據。例如lxml它既能處理xml的數據,又能處理html的數據,於是這種庫會劃分子模塊,lxml.html模塊專門負責html相關的數據。
自己來實現多種導入方法
我們現在自己來寫代碼,實現這多種導入方法。
我們創建一個文件夾DocParser,在裡面分別創建兩個文件main.py和util.py,他們的內容如下:
util.py文件:
def write(): print('write 函數被調用!') main.py文件: import util util.write()
現在我們把main.py的導入方式修改一下(結果與上面相同):
from util import write write()
現在,我們來創建一個文件夾microsoft,裡面再添加一個文件parse.py:
from util import write write()
此時我們在 main.py中對它進行調用:
def read(): print('我是 microsoft 文件夾下面的 parse.py 中的 read函數')
我們也可以用另一種方法:
from microsoft import parse parse.read()
但是,你不能直接導入microsoft
import microsoft
microsoft.parse.read
無論你使用的是import xxx還是from xxx.yyy.zzz.www import qqq,你導入進來的東西,要不就是一個模塊(對應到.py 文件的文件名),或者是某個.py 文件中的函數名、類名、變量名。
無論是import xxx還是from xxx import yyy,你導入進來的都不能是一個文件夾的名字。
可能有這樣一種情況,就是某個函數名與文件的名字相同,例如:
在 microsoft文件夾裡面有一個microsoft.py文件,這個文件裡面有一個函數叫做microsoft,那麼你的代碼可以寫為:
from microsoft import microsoft`
microsoft.microsoft()
但請註意分辨,這裡你導入的還是模塊,隻不過microsoft.py文件名與它所在的文件夾名恰好相同而已。
結論
無論是使用import還是from import,第一個要求是代碼能夠正常運行,其次,根據代碼維護性,團隊編碼風格來確定選擇哪一種方案。
如果我們隻會使用到某個模塊下面的一個函數(或者常量、類)並且名字不會產生混淆,可識別性高,那麼from 模塊名 import 函數名這沒有什麼問題。
如果我們會用到一個模塊下面的多個函數,或者是我們將要使用的函數名、常量名、類名可能會讓人產生混淆(例如 re.S、re.I),那麼這種情況下,import 模塊名然後再 模塊名.xxx來調用會讓代碼更加清晰,更好維護。
但無論什麼情況下,都禁止使用from xxx import *這種寫法,它會給你帶來無窮無盡的噩夢。
到此這篇關於Python import與from import使用和區別解讀的文章就介紹到這瞭,更多相關Python import和from import區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Python 獲取今天任意時刻的時間戳的方法
- 利用Python實現翻譯HTML中的文本字符串
- 深入瞭解Python中的時間處理函數
- python非標準時間的轉換
- Python標準庫之日期、時間和日歷模塊