1.模塊
模塊簡單理解就是一組功能的集合,
在Python中,一個檔案(.py)就是一個模塊,檔案名即模塊名,
模塊的好處是大大提高代碼的可維護性,其次,代碼不必從零開始,當一個模塊撰寫完畢,就可以被其他地方參考,
模塊可以包含可執行的陳述句和函式的定義,這些陳述句的目的是初始化模塊,它們只在模塊名第一次遇到匯入import陳述句時才執行(import陳述句是可以在程式中的任意位置使用的,且針對同一個模塊很import多次,為了防止你重復匯入,python的優化手段是:第一次匯入后就將模塊名加載到記憶體了,后續的import陳述句僅是對已經加載大記憶體中的模塊物件增加了一次參考,不會重新執行模塊內的陳述句)
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#定義名為learn.py的模塊
print('beginning learn module')
modulename = 'learn'
def fun1():
print('hello fun1')
def fun2():
print('hello fun2')
print('end learn module')
#在另外一個檔案中匯入這個模塊
import learn
import learn
#列印輸出
beginning learn module
end learn module
#可以發現只列印了一次,是因為每次匯入模塊時,解釋器都回去檢查一下這個模塊有沒有之前被導過,
模塊匯入
首先決議器是找到這個模塊,然后判斷模塊是否被匯入過,
如果沒有匯入,則:
創建一個屬于這個模塊的命名空間;如果用戶沒有定義變數來參考這個模塊的記憶體地址的話,那么就使用模塊的名稱來參考這個模塊的記憶體地址;如果用戶使用as來指定變數接受這個記憶體地址的話,那么就將記憶體地址賦值給這個變數;且下文在呼叫時只能使用這個變數進行呼叫不能再使用模塊名進行呼叫了,然后執行這個模塊中的代碼;
如果已經匯入,則:
解釋器不會重新執行模塊內的陳述句,后續的import陳述句僅僅是對已經加載到記憶體中的模塊的物件增加一次參考;
import module
#或
import module1, module2, module3
模塊別名
模塊在匯入的時候開辟了新空間記憶體,默認是使用模塊的名稱來參考這個記憶體地址的,有時候模塊的名稱很長再加上執行呼叫里面的功能的時候,就顯的很不方便,為了更好的使用模塊,我們可以給模塊起別名;
也就是在匯入模塊的時候我們不讓它使用默認的名字來參考記憶體地址,而是由我們自己定義的變數來參考這個模塊的記憶體地址;
import module as m
這樣的話就表示使用變數m來參考這個記憶體地址,然后我們在文中再使用這個模塊的時候,只要使用m來呼叫這個模塊里的功能即可,
匯入多個模塊
import os,time,sys,re #每個模塊之間用逗號隔開
#或
import os
import time
import sys
規范建議:模塊應該一個一個的匯入,先后順序為:內置模塊---->擴展(第三方)模塊------>自定義模塊;
順序說明:我們知道匯入模塊其實就是在執行這個模塊,我們不確定擴展模塊或自定義模塊里有沒有某個功能呼叫了內置模塊,所以,我們在匯入模塊時,應先匯入解釋器內置的模塊,然后在匯入擴展模塊,最后匯入自定義模塊,
from.....import
在使用一個模塊時往往我們只需要使用其中某一個或者幾個功能,如果直接用import module則會將模塊全部匯入,
比如上面的learn.py模塊中我只想使用fun1函式功能,則可以這樣匯入:
from learn import fun1
from.....import 也支持as模式,也支持匯入某個模塊的多個功能:
from learn import fun1 as f1
from learn import fun1 ,fun2
from.....import *
表示匯入模塊中所有的不是以下劃線(_)開頭的名字都匯入到當前位置,大部分情況下我們的python程式不應該使用這種匯入方式,因為你不知道你匯入什么名字,很有可能會覆寫掉你之前已經定義的名字,而且可讀性極其的差,在互動式環境中匯入時沒有問題,
還有一點要說的是,如果使用* 的方式進行了匯入,這時只想使用里面的某個或某些功能時,可以使用__all__來進行約束;
注意:__all__只是用來約束*方式的,其他方式匯入的話,不會生效;具體使用見例子:
#定義名為learn.py的模塊
print('beginning learn module')
modulename = 'learn'
def fun1():
print('hello fun1')
def fun2():
print('hello fun2')
print('end learn module')
#匯入呼叫
from learn import *
fun1()
print(modulename)
fun2()
#輸出如下:
beginning learn module
end learn module
hello fun1
learn
hello fun2
現在對其進行約束一下,要求只能使用fun1()功能;
我們在learn模塊開頭加入一下
__all__ = ["func1"]
#運行輸出:
beginning learn module
end learn module
hello fun1
Exception has occurred: NameError
name 'modulename' is not defined
File "D:\zPY\test\test_learn.py", line 9, in <module>
print(modulename)
作用域
在一個模塊中,可能會定義很多函式和變數,但有的函式和變數我們希望給別人使用,有的函式和變數我們希望僅僅在模塊內部使用,在Python中,是通過_前綴來實作的,
正常的函式和變數名是公開的(public),可以被直接參考,比如:abc,x123,PI等;
類似__xxx__這樣的變數是特殊變數,可以被直接參考,但是有特殊用途,比如上面的__author__,__name__就是特殊變數,hello模塊定義的檔案注釋也可以用特殊變數__doc__訪問,我們自己的變數一般不要用這種變數名;
類似_xxx和__xxx這樣的函式或變數就是非公開的(private),不應該被直接參考,比如_abc,__abc等;
之所以我們說,private函式和變數“不應該”被直接參考,而不是“不能”被直接參考,是因為Python并沒有一種方法可以完全限制訪問private函式或變數,但是,從編程習慣上不應該參考private函式或變數,
2.包
包是一種管理Python模塊命名空間的形式,包是一個有層次的檔案目錄結構,由模塊和子包組成,通俗的講,包就是(一定)包含__init__.py檔案的檔案夾,
package_a
├── __init__.py
├── module_a1.py
└── module_a2.py
包匯入
在匯入一個包的時候,Python 會根據 sys.path 中的目錄來尋找這個包中包含的子目錄,
目錄只有包含一個叫做 init.py 的檔案才會被認作是一個包,主要是為了避免一些濫俗的名字(比如叫做 string)不小心的影響搜索路徑中的有效模塊,
最簡單的情況,放一個空的 :file:init.py就可以了,
import package_a.module_a1
跟之前的模塊匯入一樣,在__init__.py檔案中可以定義__all__變數來控制from package import *的匯入,如下:
__all__ = ["fun1", "fun2"]
這種情況下from package import *只能匯入fun1和fun2函式,其他的都不能使用,
注意:
當使用 from package import item 這種形式的時候,對應的 item 既可以是包里面的子模塊(子包),或者包里面定義的其他名稱,比如函式,類或者變數,
import 語法會首先把 item 當作一個包定義的名稱,如果沒找到,再試圖按照一個模塊去匯入,如果還沒找到,拋出一個 :exc:ImportError 例外,
反之,如果使用形如 import item.subitem.subsubitem這種匯入形式,除了最后一項,都必須是包,而最后一項則可以是模塊或者是包,但是不可以是類,函式或者變數的名字,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/224484.html
標籤:其他
上一篇:Python學習筆記5:模塊/包
