『無為則無心』Python函式 — 36、Python中的模組

繁華似錦Fighting 發表於 2022-01-25
Python

1、模組介紹

(1)模組概念

Python 模組(Module),就是一個 Python 檔案,以.py結尾的檔案。檔案中包含了 Python 物件定義和Python語句。模組能定義函式,類和變數,模組裡也能包含可執行的程式碼。(模組就相當於Java中的工具類)

  • 用直白的話說:模組化指將一個完整的程式分解為一個一個小的模組,通過將模組組合,來搭建出一個完整的程式。
  • 換種方式說,不採用模組化,也就是統一將所有的程式碼編寫到一個檔案中。採用模組化,就是將程式功能分別編寫到不同的檔案中。

注意:

  • 模組名要符號識別符號的規範。
  • 可以引入同一個模組多次,但是模組的例項只會建立一個。
  • import可以在程式的任意位置呼叫,但是一般情況下,import語句都會統一寫在程式的開頭。

(2)模組化的優點

  • 方便開發,協同工作。
  • 方便維護,功能檔案清晰。
  • 模組可以複用,可控制。

2、匯入模組

(1)匯入模組的方式

  1. import 模組名
  2. from 模組名 import 功能名
  3. from 模組名 import *
  4. import 模組名 as 別名
  5. from 模組名 import 功能名 as 別名

(2)匯入方式詳解

1)import

  • 語法
    # 1. 匯入模組:模組名就是python檔案的名字,注意不要.py。
    import 模組名
    import 模組名1, 模組名2... # 支援但規範不推薦
    
    # 2. 呼叫功能
    模組名.功能名()
    
  • 體驗
    # 需求:math模組下sqrt() 開平方計算
    
    # 匯入模組,math是關於數學運算相關的模組
    import math
    
    # 開平方
    print(math.sqrt(9))  # 3.0
    

2)from ... import ...

  • 語法
    from 模組名 import 功能名1, 功能名2, 功能名3...
    
  • 體驗
    # 直接匯入模組中的功能
    from math import sqrt
    
    # 直接使用該功能,不需要書寫模組名.功能
    print(sqrt(9))  # 3.0
    

3)from ... import *

  • 語法
    from 模組名 import *
    
  • 體驗
    # 和上面(2)一樣,只不過功能名變成了全部匯入
    from math import *
    print(sqrt(9))  # 3.0
    

該種方式會引入到模組中所有內容,一般不會使用。

因為這種方式引入模組的內容更多,沒用到的功能也會一起引入。就相當於把一個模組中的所有內容賦值到當前Python檔案中了。

如果遇到重名的方法或者變數的話,會產生覆蓋,後邊的會覆蓋前邊的。這個可以檢視第4點。

4)as定義別名

為了提高工作效率,原有的模組名或者功能名不方便記憶或使用,我們就可以給模組名或者功能名定義別名。

模組名或者功能名定義了別名後,只能使用別名呼叫功能。同時應用該種特性可以避免模組中的屬性或方法和當前檔案中的屬性和方法同名而產生的覆蓋現象。

  • 語法
    # 模組定義別名
    import 模組名 as 別名
    
    # 功能定義別名
    from 模組名 import 功能 as 別名
    
  • 體驗
    # 需求: 執行後暫停2秒列印hello
    
    # 模組別名
    import time as tt
    
    tt.sleep(2)
    print('hello')
    
    # 功能別名
    from time import sleep as sl
    sl(2)
    print('hello')
    

3、製作模組

在Python中,每個Python檔案都可以作為一個模組,模組的名字就是檔案的名字。

自定義模組名必須要符合識別符號命名規則。

(1)定義模組

新建一個Python檔案,命名為my_module1.py,並定義testA函式。

# 需求:定義一個函式,求兩個數的和
def testA(a, b):
    print(a + b)

(2)測試模組(__main__變數)

在實際開中,當一個開發人員編寫完一個模組後,為了讓模組能夠在專案中達到想要的效果,這個開發人員會自行在py檔案中新增一些測試資訊.,例如,在my_module1.py檔案中新增測試程式碼。

def testA(a, b):
    print(a + b)


testA(1, 1)

此時,無論是當前檔案,還是其他已經匯入了該模組的檔案,在執行的時候都會自動執行testA函式的呼叫。

解決辦法如下:

def testA(a, b):
    print(a + b)

# 只在當前檔案中呼叫該函式,才執行的測試程式碼
# 也就是說這部分測試程式碼程式碼,只要當前檔案作為主模組的執行時候才需要執行的程式碼
# 而當模組被其他模組引入時,是不需要執行的,
# 此時我們就必須要檢查當前模組是否是主模組,如執行if __name__ == '__main__':
if __name__ == '__main__':
    testA(1, 1)

說明:

在每一個模組內部都有一個__name__屬性,__name__屬性是一個系統變數,是模組的識別符號。

通過這個屬性可以獲取到模組的名字。

如果__name__使用在Python檔案自身模組檔案中,__name__的值就為'__main__',又稱之為主模組。

如果__name__不是在自身檔案中被呼叫,則__name__的值為所在模組檔案的真實檔名。

可以是用print(__name__)檢視__name__的值。

在匯入模組的檔案中直接執行檔案即可檢視,不需要寫任何程式碼,因為已經寫在匯入的模組檔案中了。

(3)呼叫模組

# 匯入自定義模組
import my_module1

# 呼叫模組中的功能
my_module1.testA(1, 1)

(4)注意事項

注意1

如果使用from ... import ...from ... import *匯入多個模組的時候,且模組內有同名功能。當呼叫這個同名功能的時候,呼叫到的是後面匯入的模組的功能。

體驗:

# 模組my_module1程式碼
def my_test(a, b):
    print(a + b)

# 模組my_module2程式碼
def my_test(a, b):
    print(a - b)

# 匯入模組和呼叫功能程式碼
from my_module1 import my_test
from my_module2 import my_test

# my_test函式是模組2中的函式
my_test(1, 1)

注意2

在模組中在一個變數前新增了一個_,這個變數只能在模組內部訪問,在通過import *引入時,不會引入_開頭的變數。

# 模組my_module1程式碼
_c = 30

from my_module1 import *
print(_c)  # 報錯未定義
print(c)  # 報錯未定義

4、模組定位順序

當匯入一個模組,Python解析器對模組位置的搜尋順序是:

  1. 當前目錄(就是當前Python檔案所在的資料夾)
  2. 如果不在當前目錄,Python則搜尋在shell變數PYTHONPATH下的每個目錄。
  3. 如果都找不到,Python會察看預設路徑。UNIX下,預設路徑一般為/usr/local/lib/python/

模組搜尋路徑儲存在system模組的sys.path變數中。變數裡包含當前目錄,PYTHONPATH和由安裝過程決定的預設目錄。

# sys.path
# 他是一個列表,列表中儲存的是模組的搜尋路徑,這些路徑我們不要隨便去動
# ['C:\\Users\\lilichao\\Desktop\\resource\\course\\lesson_06\\code',
# 'C:\\dev\\python\\python36\\python36.zip',
# 'C:\\dev\\python\\python36\\DLLs',
# 'C:\\dev\\python\\python36\\lib',
# 'C:\\dev\\python\\python36',
# 'C:\\dev\\python\\python36\\lib\\site-packages']
# pprint.pprint(sys.path)

注意:

  • 自己的檔名不要和已有模組名重複,否則導致原有的模組功能無法使用。
    原因:Python解析器對模組位置的搜尋順序是由近及遠。
  • 使用from 模組名 import 功能的時候,如果功能名字重複,呼叫到的是最後定義或匯入的功能。
    • 也就是第三行和第四行匯入的模組重名,則算第四行匯入的。
    • 如果匯入的模組中的功能和檔案中定義的方法重名,也是誰在後,算誰的,前者被覆蓋。

5、__all__

如果一個模組檔案中有__all__變數,當使用from xxx import *匯入時,只能匯入這個列表中的元素(就是在這個列表裡的功能)。

my_module1模組程式碼

__all__ = ['testA']


def testA():
    print('testA')


def testB():
    print('testB')

匯入模組的檔案程式碼

from my_module1 import *
testA()
testB()

輸出結果:

image