系統自帶模塊(庫)
```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:
def read():
print('我是 microsoft 檔案夾下面的 parse.py 中的 read函式')
此時我們在 main.py中對它進行呼叫:
from microsoft import parse
parse.read()
我們也可以用另一種方法:
from microsoft.parse import read
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 *這種寫法,它會給你帶來無窮無盡的噩夢,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/301967.html
標籤:python
上一篇:編程筆試(決議及代碼實作):猴子吃桃。猴子第一天吃了若干個桃子,當即吃了一半,還不解饞,又多吃了一個…的C++、Java、Python、C#等語言代碼實作
