您好,登錄后才能下訂單哦!
這篇文章主要講解了“Python基礎之模塊如何使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Python基礎之模塊如何使用”吧!
模塊可以看成是一堆函數的集合體。
一個py文件內部就可以放一堆函數,因此一個py文件就可以看成一個模塊。
如果這個py文件的文件名為module.py
,模塊名則是module
。
在Python中,總共有以下四種形式的模塊:
自定義模塊:如果你自己寫一個py文件,在文件內寫入一堆函數,則它被稱為自定義模塊,即使用python編寫的.py文件
第三方模塊:已被編譯為共享庫或DLL的C或C++擴展 ,如requests
內置模塊:使用C編寫并鏈接到python解釋器的內置模塊 ,如time
包(文件夾):把一系列模塊組織到一起的文件夾(注:文件夾下有一個__init__.py文件,該文件夾稱之為包)
用第三方或者內置的模塊是一種拿來主義,可以極大地提升開發效率。
自定義模塊,將我們自己程序中用到的公共功能,寫入一個python文件,然后程序的各部分組件可以通過導入的方式來引用自定義模塊的功能。
一般我們使用import和from...import...導入模塊。
以下述spam.py內的文件代碼為例。
# spam.py print('from the spam.py') money = 1000 def read1(): print('spam模塊:', money) def read2(): print('spam模塊') read1() def change(): global money money = 0
語法如下:
import module1[, module2[,... moduleN]
import導入的模塊,訪問需要加前綴。
import首次導入模塊發生了3件事:
以模塊為準創造一個模塊的名稱空間
執行模塊對應的文件,將執行過程中產生的名字都丟到模塊的名稱空間
在當前執行文件中拿到一個模塊名
注意:模塊的重復導入會直接引用之前創造好的結果,不會重復執行模塊的文件。
# run.py import spam # from the spam.py import spam money = 111111 spam.read1() # 'spam模塊:1000' spam.change() print(spam.money) # 0 print(money) # 111111
# run.py import spam as sm money = 111111 sm.money sm.read1() # 'spam模塊:1000' sm.read2 sm.change() print(money) # 1000
import spam, time, os # 推薦使用下述方式 import spam import time import os
語法如下:
from modname import name1[, name2[, ... nameN]]
這個聲明不會把整個模塊導入到當前的命名空間中,它只會將模塊里的一個或多個函數引入進來。
from...import...導入的模塊,訪問不需要加前綴。
from...import...首次導入模塊發生了3件事:
以模塊為準創造一個模塊的名稱空間
執行模塊對應的文件,將執行過程中產生的名字都丟到模塊的名稱空間
在當前執行文件的名稱空間中拿到一個名字,該名字直接指向模塊中的某一個名字,意味著可以不用加任何前綴而直接使用
優點:不用加前綴,代碼更加精簡
缺點:容易與當前執行文件中名稱空間中的名字沖突
# run.py from spam import money from spam import money,read1 money = 10 print(money) # 10
# spam.py __all__ = ['money', 'read1'] # 只允許導入'money'和'read1' # run.py from spam import * # 導入spam.py內的所有功能,但會受限制于__all__ money = 111111 read1() # 'spam模塊:1000' change() read1() # 'spam模塊:0' print(money) # 111111
以下情況會出現循環導入:
# m1.py print('from m1.py') from m2 import x y = 'm1' # m2.py print('from m2.py') from m1 import y x = 'm2'
可以使用函數定義階段只識別語法的特性解決循環導入的問題,或從本質上解決循環導入的問題,但是最好的解決方法是不要出現循環導入。
方案一:
# m1.py print('from m1.py') def func1(): from m2 import x print(x) y = 'm1' # m2.py print('from m2.py') def func1(): from m1 import y print(y) x = 'm2'
方案二:
5、# m1.py print('from m1.py') y = 'm1' from m2 import x # m2.py print('from m2.py') x = 'm2' from m1 import y
內置的函數 dir() 可以找到模塊內定義的所有名稱。以一個字符串列表的形式返回:
dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']
如果沒有給定參數,那么 dir() 函數會羅列出當前定義的所有名稱:
a = [1, 2, 3, 4, 5] import fibo fib = fibo.fib print(dir()) # 得到一個當前模塊中定義的屬性列表 # ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys'] b = 5 # 建立一個新的變量 'a' print(dir()) # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b'] del b # 刪除變量名a print(dir()) # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a']
如果我們在運行run.py文件的時候,快速刪除mmm.py文件,我們會發現文件會繼續運行,而不會報錯,因為mmm已經被導入內存當中。如果我們再一次運行run.py時會報錯,因為mmm.py已經被刪除了。
# test.py import m1 # 從m1.py文件中導入的,然后會生成m1模塊的名稱空間 import time # 刪除m1.py文件,m1模塊的名稱空間仍然存在 time.sleep(10) import m1 # 不報錯,一定不是從文件中獲取了m1模塊,而是從內存中獲取的
驗證先從內置中找,不會先找自定義的time.py文件。
# time.py print('from time.py') # run.py import time print(time) #
import sys for n in sys.path: print(n) # C:\PycharmProjects\untitled\venv\Scripts\python.exe C:/PycharmProjects/untitled/hello.py # C:\PycharmProjects\untitled # C:\PycharmProjects\untitled # C:\Python\Python38\python38.zip # C:\Python\Python38\DLLs # C:\Python\Python38\lib # C:\Python\Python38 # C:\PycharmProjects\untitled\venv # C:\PycharmProjects\untitled\venv\lib\site-packages
如果mmm.py在C:\PycharmProjects\untitled\day16路徑下,而執行文件路徑為C:\PycharmProjects\untitled,如果普通導入一定會報錯,我們可以把C:\PycharmProjects\untitled\day16添加到環境變量sys.path中,防止報錯。
# run.py import sys sys.path.append(r'C:\PycharmProjects\untitled\day16') print(sys.path) import mmm mmm.f1()
假設我們有如下目錄結構的文件,文件內代碼分別是:
而hello和spam.py不是同目錄下的,因此run.py的環境變量無法直接找到m2,需要從文件夾導入
from aa import spam print(spam.money)
一個模塊被另一個程序第一次引入時,其主程序將運行。如果我們想在模塊被引入時,模塊中的某一程序塊不執行,我們可以用__name__屬性來使該程序塊僅在該模塊自身運行時執行。
python文件總共有兩種用途,一種是執行文件;另一種是被當做模塊導入。
每個模塊都有一個__name__屬性,當其值是'__main__'時,表明該模塊自身在運行,否則是被引入。
1、當run.py運行的時候,aaa.py被當做引用模塊,它的__name__ == 'aaa'(模塊名),會執行aaa.py中的f1()。
# aaa.py x = 1 def f1(): print('from f1') f1() # run.py import aaa
2、aaa.py被當做可執行文件時,加上__name__ == '__main__',單獨運行aaa.py才會執行aaa.py中的f1()。 run.py運行時可以防止執行f1()。
# aaa.py x = 1 def f1(): print('from f1') if __name__ == '__main__': f1()
包是一種管理 Python 模塊命名空間的形式,包的本質就是一個含有.py
的文件的文件夾。
包采用"點模塊名稱"。比如一個模塊的名稱是 A.B, 那么他表示一個包 A中的子模塊 B 。
目錄只有包含一個叫做 __init__.py 的文件才會被認作是一個包。
在導入一個包的時候,Python 會根據 sys.path 中的目錄來尋找這個包中包含的子目錄。
導入包發生的三件事:
創建一個包的名稱空間
由于包是一個文件夾,無法執行包,因此執行包下的.py文件,將執行過程中產生的名字存放于包名稱空間中(即包名稱空間中存放的名字都是來自于.py)
在當前執行文件中拿到一個名字aaa,aaa是指向包的名稱空間的
導入包就是在導入包下的.py,導入m1就是導入m1中的__init__。
import ... :
import item.subitem.subsubitem 這種導入形式,除了最后一項,都必須是包,而最后一項則可以是模塊或者是包,但是不可以是類,函數或者變量的名字。
from ... import...:
當使用 from package import item 這種形式的時候,對應的 item 既可以是包里面的子模塊(子包),或者包里面定義的其他名稱,比如函數,類或者變量。
import 可以每次只導入一個包里面的特定模塊,他必須使用全名去訪問。
import aaa.bbb.m3 print(aaa.bbb.m3.func3())
import方式不能導入函數、變量:import aaa.bbb.m3.f3錯誤
這種方式不需要那些冗長的前綴進行訪問
from aaa.bbb import m3 print(m3.func3())
這種方式不需要那些冗長的前綴進行訪問
from aaa.bbb.m3 import func3 print(func3())
# aaa/.py from aaa.m1 import func1 from aaa.m2 import func2
.代表當前被導入文件所在的文件夾
..代表當前被導入文件所在的文件夾的上一級
...代表當前被導入文件所在的文件夾的上一級的上一級
from .m1 import func1 from .m2 import func2
導入語句遵循如下規則:如果包定義文件 __init__.py 存在一個叫做 __all__ 的列表變量,那么在使用 from package import * 的時候就把這個列表中的所有名字作為包內容導入。
這里有一個例子,在:file:sounds/effects/__init__.py中包含如下代碼:
__all__ = ["echo", "surround", "reverse"]
這表示當你使用from sound.effects import *這種用法時,你只會導入包里面這三個子模塊。
為了提高程序的可讀性與可維護性,我們應該為軟件設計良好的目錄結構,這與規范的編碼風格同等重要,簡而言之就是把軟件代碼分文件目錄。假設你要寫一個ATM軟件,你可以按照下面的目錄結構管理你的軟件代碼:
ATM/ |-- core/ | |-- src.py # 業務核心邏輯代碼 | |-- api/ | |-- api.py # 接口文件 | |-- db/ | |-- db_handle.py # 操作數據文件 | |-- db.txt # 存儲數據文件 | |-- lib/ | |-- common.py # 共享功能 | |-- conf/ | |-- settings.py # 配置相關 | |-- bin/ | |-- run.py # 程序的啟動文件,一般放在項目的根目錄下,因為在運行時會默認將運行文件所在的文件夾作為sys.path的第一個路徑,這樣就省去了處理環境變量的步驟 | |-- log/ | |-- log.log # 日志文件 | |-- requirements.txt # 存放軟件依賴的外部Python包列表,詳見https://pip.readthedocs.io/en/1.1/requirements.html |-- README # 項目說明文件
# settings.py import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DB_PATH = os.path.join(BASE_DIR, 'db', 'db.txt') LOG_PATH = os.path.join(BASE_DIR, 'log', 'user.log') # print(DB_PATH) # print(LOG_PATH)
# common.py import time from conf import settings def logger(msg): current_time = time.strftime('%Y-%m-%d %X') with open(settings.LOG_PATH, mode='a', encoding='utf-8') as f: f.write('%s %s' % (current_time, msg))
# src.py from conf import settings from lib import common def login(): print('登陸') def register(): print('注冊') name = input('username>>: ') pwd = input('password>>: ') with open(settings.DB_PATH, mode='a', encoding='utf-8') as f: f.write('%s:%s\n' % (name, pwd)) # 記錄日志。。。。。。 common.logger('%s注冊成功' % name) print('注冊成功') def shopping(): print('購物') def pay(): print('支付') def transfer(): print('轉賬') func_dic = { '1': login, '2': register, '3': shopping, '4': pay, '5': transfer, } def run(): while True: print(""" 1 登陸 2 注冊 3 購物 4 支付 5 轉賬 6 退出 """) choice = input('>>>: ').strip() if choice == '6': break if choice not in func_dic: print('輸入錯誤命令,傻叉') continue func_dic[choice]()
# run.py import sys import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from core import src if __name__ == '__main__': src.run()
感謝各位的閱讀,以上就是“Python基礎之模塊如何使用”的內容了,經過本文的學習后,相信大家對Python基礎之模塊如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。