Python模塊基礎(chǔ)指南之import的四種導(dǎo)入方式全對(duì)比
一、開(kāi)篇:同一種需求,四種寫(xiě)法
Python提供了四種導(dǎo)入模塊的方式,每種都有不同的適用場(chǎng)景:
# 方式一:導(dǎo)入整個(gè)模塊 import math # 方式二:導(dǎo)入模塊并起別名 import math as m # 方式三:從模塊中導(dǎo)入特定名稱(chēng) from math import sqrt, pi # 方式四:導(dǎo)入模塊中的所有公開(kāi)名稱(chēng) from math import *
這四種方式表面上看都能讓你使用math模塊的功能,但它們?cè)诿臻g、內(nèi)存占用、代碼可讀性和潛在風(fēng)險(xiǎn)上有著本質(zhì)區(qū)別。選擇哪種方式,直接影響代碼的質(zhì)量。
二、四種方式逐一詳解
2.1 方式一:import 模塊名
# import 模塊名 —— 導(dǎo)入整個(gè)模塊對(duì)象 import math # 這創(chuàng)建了一個(gè)變量 math,指向整個(gè)math模塊對(duì)象 print(type(math)) # <class 'module'> print(dir(math)[:10]) # ['__doc__', ..., 'acos', 'acosh', ...] # 使用:必須通過(guò)模塊名訪問(wèn) print(math.pi) # 3.141592653589793 print(math.sqrt(16)) # 4.0 print(math.sin(math.pi / 2)) # 1.0 # ? 優(yōu)點(diǎn): # 1. 命名空間清晰——math.sqrt一看就知道哪來(lái)的 # 2. 不會(huì)污染當(dāng)前命名空間 # 3. 不會(huì)和已有的變量名沖突 # ? 缺點(diǎn): # 1. 每次都寫(xiě)模塊名——如果模塊名很長(zhǎng)會(huì)比較啰嗦 # 2. 導(dǎo)入了整個(gè)模塊(雖然通常不是問(wèn)題) # ?? 適用場(chǎng)景: # - 大多數(shù)情況下的默認(rèn)選擇 # - 模塊名不太長(zhǎng)時(shí) # - 需要模塊中多個(gè)功能時(shí)
2.2 方式二:import 模塊名 as 別名
# import 模塊名 as 別名 —— 給模塊起一個(gè)短名字 import numpy as np import pandas as pd import matplotlib.pyplot as plt import tensorflow as tf # 使用別名訪問(wèn) arr = np.array([1, 2, 3, 4, 5]) print(np.mean(arr)) # 3.0 # ? 優(yōu)點(diǎn): # 1. 輸入更少(某些庫(kù)的名字本身就很長(zhǎng)) # 2. 符合社區(qū)約定(np是指numpy幾乎已成標(biāo)準(zhǔn)) # 3. 解決命名沖突(兩個(gè)模塊有相同的名字) # ? 缺點(diǎn): # 1. 如果用了非標(biāo)準(zhǔn)的別名,降低可讀性 # import math as pineapple # 不要這樣! # pineapple.sqrt(16) # 這段代碼會(huì)讓同事困惑 # ? 不推薦的用法 # 除非有明確的重命名理由(如避免沖突),否則不要隨意起別名 import json as js # 不推薦——json本身就不長(zhǎng) # ? 推薦的用法(社區(qū)約定) import numpy as np # 標(biāo)準(zhǔn)約定 import pandas as pd # 標(biāo)準(zhǔn)約定 import matplotlib.pyplot as plt # 標(biāo)準(zhǔn)約定
2.3 方式三:from 模塊名 import 名稱(chēng)
# from 模塊名 import 名稱(chēng) —— 將特定名稱(chēng)導(dǎo)入當(dāng)前命名空間
from math import sqrt, pi, sin, cos
# 可以直接使用這些名稱(chēng),不需要模塊名前綴
print(sqrt(16)) # 4.0
print(pi) # 3.141592653589793
print(sin(pi / 2)) # 1.0
# 未導(dǎo)入的名稱(chēng)仍然需要通過(guò)模塊名訪問(wèn)
# print(math.ceil(3.14)) # NameError! math沒(méi)有被導(dǎo)入
import math # 如果需要其他功能,單獨(dú)導(dǎo)入模塊
print(math.ceil(3.14)) # 4
# 可以同時(shí)導(dǎo)入多個(gè)名稱(chēng)
from os.path import join, exists, isfile
print(join("dir", "file.txt")) # dir/file.txt
# ? 優(yōu)點(diǎn):
# 1. 代碼更簡(jiǎn)潔——不需要寫(xiě)模塊名
# 2. 明確導(dǎo)入了什么——讀者知道你用了模塊的哪些功能
# 3. 可以只導(dǎo)入需要的——雖然不會(huì)減少內(nèi)存占用
# ? 缺點(diǎn)和陷阱:
# 1. 可能和已有的變量名沖突
pi = "我自定義的pi"
from math import pi # 覆蓋了上面的pi!
print(pi) # 3.141592653589793 —— 不是 "我自定義的pi"!
# 2. 導(dǎo)入太多名稱(chēng)會(huì)讓命名空間混亂
from math import sin, cos, tan, asin, acos, atan, sqrt, pi, e, floor, ceil, ...
# 如果都是從不同模塊導(dǎo)入的,閱讀者很難知道每個(gè)名稱(chēng)來(lái)自哪里
# 3. 變量綁定問(wèn)題——from import導(dǎo)入的是值的引用
# 如果源模塊中的值改變了,from導(dǎo)入的變量不會(huì)自動(dòng)更新
2.4 方式四:from 模塊名 import *
# from 模塊名 import * —— 導(dǎo)入模塊的所有"公開(kāi)"名稱(chēng)
# ?? 這是最不推薦的方式!原因如下:
# 1. 你不知道導(dǎo)入了什么
from math import *
# 現(xiàn)在你有:sin, cos, tan, sqrt, pi, e, floor, ceil, ...
# 以及你不經(jīng)意間覆蓋的:pow, abs, sum, ...(任何同名變量)
# 2. 污染命名空間——導(dǎo)致難以發(fā)現(xiàn)的命名沖突
def sin(x):
"""我自己寫(xiě)的sin函數(shù):返回字符串"""
return "這不是正弦"
from math import * # 剛才定義的sin被覆蓋了!
print(sin(0)) # 0.0 —— 不是 "這不是正弦"
# 3. 可讀性極差
# 讀代碼的人不知道sum來(lái)自哪里——是內(nèi)置的?math的?還是你定義的?
# from math import *
# from statistics import *
# sum(...) # 這是哪個(gè)sum?
# 4. PEP 8強(qiáng)烈不推薦
# "Wildcard imports (from <module> import *) should be avoided"
# ? 唯一可接受的例外:
# 在 __init__.py 中控制包的公開(kāi)API
# mypackage/__init__.py:
# from .module_a import ClassA, func_b
# from .module_b import ClassC
# __all__ = ["ClassA", "func_b", "ClassC"]
2.5 __all__控制from import *的行為
# __all__是一個(gè)模塊級(jí)變量
# 定義了 from module import * 時(shí)哪些名稱(chēng)會(huì)被導(dǎo)入
# 假設(shè)有一個(gè)模塊 my_module.py:
"""
__all__ = ["public_func", "PublicClass"] # 白名單
def public_func():
'''這個(gè)函數(shù)會(huì)被導(dǎo)出'''
pass
def _private_func():
'''下劃線(xiàn)開(kāi)頭的默認(rèn)不會(huì)被導(dǎo)出'''
pass
class PublicClass:
'''這個(gè)類(lèi)會(huì)被導(dǎo)出'''
pass
class _PrivateClass:
'''下劃線(xiàn)開(kāi)頭的默認(rèn)不會(huì)被導(dǎo)出'''
pass
internal_data = "不會(huì)被導(dǎo)出" # 不在__all__中
"""
# 使用:
# from my_module import *
# public_func() # ? 可用(在__all__中)
# PublicClass() # ? 可用(在__all__中)
# _private_func() # ? 不可用(_開(kāi)頭,且不在__all__中)
# internal_data # ? 不可用(不在__all__中)
# ?? __all__是一種顯式聲明模塊"公開(kāi)API"的方式
# 即使不用from import *,__all__也能作為文檔告訴使用者哪些是公開(kāi)的
三、四種方式的對(duì)比
# ?? 完整對(duì)比 # 假設(shè)要使用math、os、json三個(gè)模塊的功能 # 方式一:import —— 命名空間最清晰 import math import os import json # 使用:math.sqrt(), os.path.join(), json.dumps() # 一目了然——每個(gè)函數(shù)來(lái)自哪個(gè)模塊 # 方式二:import as —— 最靈活 import numpy as np import pandas as pd # 使用:np.array(), pd.DataFrame() # 在保持清晰的同時(shí)簡(jiǎn)化了輸入 # 方式三:from import —— 在簡(jiǎn)潔和清晰間平衡 from math import sqrt, pi from os.path import join from json import dumps, loads # 使用:sqrt(), join(), dumps() —— 簡(jiǎn)潔 # 但讀者需要記住sqrt來(lái)自math,join來(lái)自os.path # 方式四:from import * —— 簡(jiǎn)潔但危險(xiǎn)的 # from math import * # from os import * # ?? os沒(méi)有__all__,會(huì)導(dǎo)入所有名稱(chēng)! # 不到萬(wàn)不得已不要用
四、最佳實(shí)踐
# ? 推薦做法一:默認(rèn)使用 import 模塊名 import math import json import os # 清晰、安全、不會(huì)污染命名空間 # ? 推薦做法二:社區(qū)標(biāo)準(zhǔn)的別名 import numpy as np import pandas as pd import matplotlib.pyplot as plt # ? 推薦做法三:from import 特定名稱(chēng)——只導(dǎo)入幾個(gè)時(shí) from collections import defaultdict, Counter from pathlib import Path from typing import Optional, List # ? 推薦做法四:導(dǎo)入子模塊 import os.path # 導(dǎo)入子模塊 from os import path # 另一種方式 # ? 避免的做法 # 1. 不要用 from module import *(除非在__init__.py中) # 2. 不要給模塊起奇怪的別名 # 3. 不要同時(shí)用多種導(dǎo)入方式從同一個(gè)模塊導(dǎo)入 # 不好的例子: # import math # from math import sqrt # 重復(fù)了
五、總結(jié)
四種導(dǎo)入方式各有適用場(chǎng)景??傮w原則是:以代碼可讀性為第一優(yōu)先。
選型速查:
| 方式 | 適用場(chǎng)景 | 風(fēng)險(xiǎn) |
|---|---|---|
import math | 默認(rèn)選擇,使用模塊中多個(gè)功能 | 低 |
import numpy as np | 長(zhǎng)模塊名,社區(qū)約定 | 低 |
from math import sqrt | 只用到1-2個(gè)功能 | 中——命名沖突 |
from math import * | 幾乎只在__init__.py中 | 高——不推薦 |
黃金法則:寧可多寫(xiě)幾個(gè)字符,也別讓讀代碼的人猜每個(gè)名字來(lái)自哪里。
到此這篇關(guān)于Python模塊基礎(chǔ)指南之import的四種導(dǎo)入方式全對(duì)比的文章就介紹到這了,更多相關(guān)Python import模塊導(dǎo)入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python使用from...import...模塊導(dǎo)入指定內(nèi)容的方法詳解
- 一文詳解Python import導(dǎo)入模塊與模塊的搜索路徑
- Python from import導(dǎo)入模塊所有內(nèi)容的方法
- Python使用from?import導(dǎo)入模塊中的指定內(nèi)容
- Python基礎(chǔ)之import導(dǎo)入模塊并調(diào)用其函數(shù)的完整指南
- Python模塊導(dǎo)入之import、from、相對(duì)導(dǎo)入與?init.py詳解
- Python中ImportError:無(wú)法導(dǎo)入模塊的問(wèn)題解決辦法
- 詳解Python中import模塊導(dǎo)入的實(shí)現(xiàn)原理
- Python importlib動(dòng)態(tài)導(dǎo)入模塊實(shí)現(xiàn)代碼
相關(guān)文章
python 生成正態(tài)分布數(shù)據(jù),并繪圖和解析
這篇文章主要介紹了python 生成正態(tài)分布數(shù)據(jù),并繪圖和解析,幫助大家更好的利用python進(jìn)行數(shù)據(jù)分析,感興趣的朋友可以了解下2020-12-12
Python實(shí)現(xiàn)24點(diǎn)小游戲
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)24點(diǎn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Python字典操作詳細(xì)介紹及字典內(nèi)建方法分享
這篇文章主要介紹了Python字典操作詳細(xì)介紹及字典內(nèi)建方法分享,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
python爬蟲(chóng)快速響應(yīng)服務(wù)器的做法
在本篇文章里小編給大家整理的是一篇關(guān)于python爬蟲(chóng)快速響應(yīng)服務(wù)器的做法,需要的朋友們可以參考下。2020-11-11

