摘要:如果你這個(gè)腳本想要使用其它腳本里面的變量函數(shù)和類也是可以的,在你這個(gè)腳本里面用來導(dǎo)入要引用的腳本,而那個(gè)被引用的腳本就稱作模塊。
在此之前,我們運(yùn)行一些簡(jiǎn)短的Python代碼,都是通過Python解釋器(python或ipython)進(jìn)行的,如果我們退出解釋器再重新運(yùn)行解釋器后,上次敲進(jìn)去的變量、函數(shù)等都不見了,沒有保存下來。為了保存我們?cè)?jīng)寫過的代碼,就是要寫成.py文件,稱為腳本。
如果你這個(gè)腳本想要使用其它腳本里面的變量、函數(shù)和類也是可以的,在你這個(gè)腳本里面用import來導(dǎo)入要引用的腳本,而那個(gè)被引用的腳本就稱作模塊(module)。
簡(jiǎn)單來說,一個(gè)Python源碼文件(*.py)就是一個(gè)模塊。
我們的第一個(gè)Python模塊接下來,我們用文本編輯器(比如,前面介紹的VS Code)來創(chuàng)建一個(gè)名為?my_first_module.py的文件作為我們編寫的第一個(gè)模塊:
#!/usr/bin/env python3 # coding:utf-8 # Author: veelion # file name: my_first_module.py """My First Module""" MY_NAME = "My_First_Module" def my_print(a): print(MY_NAME, " print", a) def my_add(a, b): return a+b
我們的第一個(gè)Python模塊里面有一個(gè)全局變量:MY_NAME,兩個(gè)函數(shù):my_print()和my_add()。接著我們?cè)?b>這個(gè)文件所在目錄運(yùn)行Python解釋器ipython:
In [1]: import my_first_module In [2]: my_first_module? Type: module String form:File: ~/p2/tutorial/md_Python/codes/my_first_module.py Docstring: My First Module In [3]: my_first_module.MY_NAME Out[3]: "My_First_Module" In [4]: my_first_module.my_add(2, 3) Out[4]: 5 In [5]: my_first_module.my_print("猿人學(xué)") My_First_Module print 猿人學(xué)
導(dǎo)入模塊用import,模塊名稱就是文件名my_first_module.py去掉文件后綴.py后的名字。從上面ipython的使用中,我們可以看到模塊中的函數(shù)、變量都是可以被拿來用的。
注意:?Python模塊的文件名只能是字母、數(shù)字和下劃線,不能有-,+等其它符號(hào),否則導(dǎo)入會(huì)報(bào)錯(cuò),原因很簡(jiǎn)單,比如-符號(hào)會(huì)和Python里面的減號(hào)混淆。
把上面的模塊重命名為my-first-module.py,再import導(dǎo)入一下看看:
In [6]: import my-first-module File "Python模塊的二三事", line 1 import my-first-module ^ SyntaxError: invalid syntax
(1)模塊可以包含可執(zhí)行的全局語句。這些語句應(yīng)該是用于初始化該模塊,它們只在第一次被import時(shí)執(zhí)行。我們來舉個(gè)例子,創(chuàng)建兩個(gè)只包含一句print的模塊:
# m1.py print("m1 is imported")
# m2.py import m1 print("m2 is imported")
在main.py中導(dǎo)入m1和m2這兩個(gè)模塊:
import m1 import m2 import m1 print("I am main.py")
這里m1被顯性導(dǎo)入兩次,還有一次被m2陰性導(dǎo)入,一共導(dǎo)入三次,那么是不是m1 is imported會(huì)被打印3次呢?我們運(yùn)行這個(gè)腳本試試看:?python main.py。猜猜運(yùn)行結(jié)果是怎樣的?
m1 is imported m2 is imported I am main.py
結(jié)果是只被打印了一次。這就是只在第一次被import時(shí)執(zhí)行的意思。再試試把main.py中的兩個(gè)import m1都去掉,只import m2會(huì)是什么結(jié)果?
(2)每個(gè)模塊都都它自己私有的符號(hào)表,它被當(dāng)做全局符號(hào)表被該模塊中所有函數(shù)使用,也就是說,每個(gè)模塊都有自己的名字空間。因此,模塊里面可以盡情(如有必要)使用全局變量,而不用擔(dān)心它們與模塊使用者的全局變量沖突。用戶使用模塊中的全局變量也很簡(jiǎn)單:modname.itemname。
比如,my_first_module模塊中的MY_NAME使用時(shí)就是my_first_module.MY_NAME,而在你自己的腳本里面同樣可以命名MY_NAME的全局變量,而不會(huì)和my_first_module里面的沖突。
(3)模塊可以import其它模塊。模塊導(dǎo)入語句import不一定要在腳本的最開始,可以在代碼其它位置需要時(shí)導(dǎo)入。當(dāng)然,在最開始導(dǎo)入是最清晰、規(guī)范的做法。
import 模塊的各種方式我們使用import的方式很多,前面那種?import module_name的方式是最常用的,也是代碼規(guī)范推崇的用法。從語法上講還有其它方式:
(1)用from導(dǎo)入部分:
In [1]: from my_first_module import my_add In [2]: my_add(1,3) Out[2]: 4 In [3]: my_print("hi") --------------------------------------------------------------------------- NameError Traceback (most recent call last)in ----> 1 my_print("hi") NameError: name "my_print" is not defined In [4]: my_first_module.my_add(1,2) --------------------------------------------------------------------------- NameError Traceback (most recent call last) in ----> 1 my_first_module.my_add(1,2) NameError: name "my_first_module" is not defined
通過from modname import xxx的方式,我們只導(dǎo)入了my_add,調(diào)用my_print就會(huì)出錯(cuò)。并且,my_first_module模塊名稱也是未定義的,即沒有被導(dǎo)入。
(2)用from導(dǎo)入部分并重命名
跟(1)一樣,只不過把導(dǎo)入的名稱起了別名而已,使用時(shí)用別名:
from my_first_module import my_add as myadd
(3)用from導(dǎo)入全部
In [1]: from my_first_module import * In [2]: my_add(1,2) Out[2]: 3 In [3]: my_print("猿人學(xué)") My_First_Module print 猿人學(xué) In [4]: MY_NAME Out[4]: "My_First_Module"
這種方式看似簡(jiǎn)單,寫代碼時(shí)省去了模塊名稱my_first_module這個(gè)前綴。但是,這個(gè)省略帶來很大隱患,會(huì)限制我們自己命名。如果我們自己命名和模塊里面的名稱一樣,就會(huì)覆蓋模塊里面的名字。
這種import的方式是代碼規(guī)范嚴(yán)禁杜絕的
(4)重命名模塊
如果模塊名稱很長(zhǎng),我們可以給它起個(gè)短一點(diǎn)的別名,這樣寫代碼會(huì)簡(jiǎn)單些:
In [1]: import my_first_module as mfm In [2]: mfm.my_add(1,2) Out[2]: 3 In [3]: mfm.my_print("猿人學(xué)") My_First_Module print 猿人學(xué) In [4]: mfm.MY_NAME Out[4]: "My_First_Module"
這個(gè)和import my_first_module實(shí)際上一樣,只是使用的名稱變?yōu)?b>mfm。模塊的別名可以任意起,只要和其它名稱區(qū)分開來就好。
(5)模塊重新加載
我們寫完一個(gè)模塊,可能要通過Python解釋器(如ipython)進(jìn)行驗(yàn)證一下,于是運(yùn)行Python解釋器,import模塊,發(fā)現(xiàn)模塊的某個(gè)函數(shù)有錯(cuò)誤,就在編輯器修改了該函數(shù)并保存該模塊文件。繼續(xù)在剛才打開的解釋器里面驗(yàn)證那個(gè)有錯(cuò)誤的函數(shù),發(fā)現(xiàn)剛才的修改沒生效,竟然沒有生效!??!
為什么呢?為了效率,每個(gè)解釋器導(dǎo)入的模塊只導(dǎo)入一次。因此,如果你中途修改了模塊,就要出解釋器重新進(jìn)入并重新導(dǎo)入模塊才能使修改生效。如果不退出解釋器而重新導(dǎo)入模塊,不管你運(yùn)行多少次import modname都是無效的,因?yàn)榻忉屍饕豢催@個(gè)模塊已經(jīng)導(dǎo)入過了,就不費(fèi)勁再導(dǎo)入一次了。解釋器懶,你就不能懶。
或者,可以不重新啟動(dòng)解釋器而使用importlib.reload()重新導(dǎo)入。
把Python模塊當(dāng)做腳本運(yùn)行任何Python文件都可以這樣來運(yùn)行:
python3 file.py
一個(gè)文件的Python模塊當(dāng)然也可以這樣運(yùn)行。一個(gè)Python文件,前面是函數(shù)的定義,定義完要運(yùn)行,我們就要寫調(diào)用語句,最初你相到的可能是這樣的:
# Author: veelion # file: mylib.py def add(a, b): return a+b print(add(2, 3))
通過python mylib.py運(yùn)行一下,就可以得到運(yùn)行結(jié)果。
目前看起來一切正常,你看看有沒有問題?
回頭看看上面模塊二三事的第(1)條,如果這個(gè)文件當(dāng)做模塊被其它文件import時(shí),是不是也會(huì)運(yùn)行打印語句?這條打印語句往往是我們?yōu)榱蓑?yàn)證add()函數(shù)而進(jìn)行的,屬于測(cè)試階段的代碼,而交付給他人作為模塊使用時(shí),它是不需要的。那么,該怎么辦?
通過__name__屬性就可以來限制print(add(2, 3))語句的運(yùn)行。文件作為腳本運(yùn)行時(shí),它的__name__屬性是__main__,而作為模塊被import時(shí),它的__name__屬性是模塊的名稱。
先看看模塊被import時(shí)的__name__:
In [24]: import mylib 5 In [25]: mylib.__name__ Out[25]: "mylib"
我們可以看到,import mylib后打印出了5,也就是運(yùn)行了print(add(2, 3))語句。
然后,我們修改mylib.py文件,把測(cè)試語句修改一下:
# Author: veelion # file: mylib.py def add(a, b): return a+b if __name__ == "__main__": print(add(2, 3))
再次在ipython解釋器里面導(dǎo)入該模塊時(shí)就不會(huì)打印出5,也就是那句print不再執(zhí)行。
而在命令行下運(yùn)行python3 mylib.py這個(gè)腳本就會(huì)執(zhí)行那句print語句,因?yàn)檫@種執(zhí)行方式下,模塊的__name__為__main__。
這些用__name__ == "__main__"條件判斷的代碼通常是該模塊的測(cè)試代碼,或者是如何使用該模塊的示例代碼。
Python模塊總結(jié)(1)一個(gè)Python文件就是一個(gè)模塊;
(2)一個(gè)模塊可以import其它模塊;
(3)在Python解釋器運(yùn)行中,一個(gè)模塊只可以被import一次,除非使用importlib.reload();
(4)模塊中的可執(zhí)行語句(非函數(shù)、類的定義)僅在該模塊被import時(shí)執(zhí)行一次。
(5)import模塊的方式有多種,要使用最規(guī)范的方式。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/43800.html
摘要:標(biāo)準(zhǔn)模塊附帶了一個(gè)標(biāo)準(zhǔn)模塊庫。它返回一個(gè)如果調(diào)用不傳遞參數(shù),則列出當(dāng)前已經(jīng)定義的所有名字用可以查看所有的內(nèi)置類型變量函數(shù)等,方法是借助標(biāo)準(zhǔn)模塊模塊高級(jí)技巧總結(jié)的搜索路徑,順序一定要搞得清編譯后的文件內(nèi)置函數(shù)查看模塊定義的名字。 上一節(jié),我們講解了Python模塊的基礎(chǔ)知識(shí),這一節(jié)我們繼續(xù)深入了解模塊的更多知識(shí),從而讓大家全面了解、掌握和運(yùn)用模塊到我們實(shí)際的編程中。 在上一節(jié)中有一句話接...
摘要:所解包的序列中的元素?cái)?shù)量必須和賦值符號(hào)左邊的變量數(shù)量完全一致。其中,冒號(hào)標(biāo)識(shí)語句塊開始?jí)K中每一個(gè)語句都是縮進(jìn)相同量退回到和已經(jīng)閉合的塊一樣的縮進(jìn)量時(shí),表示當(dāng)前塊結(jié)束。成員資格運(yùn)算符字符串和序列比較字符串可按照字母順序比較。 print和import print打印多個(gè)表達(dá)式,用逗號(hào),隔開 print abc:, 42, nonono #輸出在每個(gè)參數(shù)之間添加空格 print在結(jié)尾處加上...
摘要:比如,模塊名表示包中名為的子模塊。例如,文件可以包含以下代碼定義了之后,就會(huì)把,,導(dǎo)入到當(dāng)前命名空間。這種導(dǎo)入使用前導(dǎo)點(diǎn)來指示相對(duì)導(dǎo)入中涉及的當(dāng)前包和父包。也就是說被執(zhí)行的主程序里面不能包含相對(duì)導(dǎo)入。 包,Package,是一種Python模塊的集合,從文件組織形式上看,包就是一個(gè)文件夾,里面放著各種模塊(.py文件),也可以有子文件夾(子包)。包名構(gòu)建了一個(gè)Python模塊的命名空間...
摘要:安裝好后,在中執(zhí)行查看版本信息,應(yīng)該會(huì)看到輸出如下信息版本號(hào)可能會(huì)不同如果提示未找到,則需要手動(dòng)將用戶基礎(chǔ)目錄下的添加到中。相關(guān)文章基礎(chǔ)教程系列第篇開天坑啦 showImg(https://segmentfault.com/img/bV4GZu?w=1262&h=911); 之前說好的 「Odoo 基礎(chǔ)教程系列」終于來了(撒花)~剛過完年重新投入到工作中,一下子事情有點(diǎn)多都要忙不過來了...
閱讀 3809·2021-11-12 10:34
閱讀 2824·2021-09-22 15:14
閱讀 791·2019-08-30 15:53
閱讀 3207·2019-08-30 12:53
閱讀 1296·2019-08-29 18:32
閱讀 2774·2019-08-29 16:41
閱讀 1071·2019-08-26 13:40
閱讀 1816·2019-08-23 18:07