python基礎---模塊與包


1、模塊導入方法


常見的場景:

一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的後綴,導入模塊可以實現功能的重複利用


import加載的模塊分爲四個通用類別: 

1 使用python編寫的代碼(.py文件)

2 已被編譯爲共享庫或DLLCC++擴展

3 包好一組模塊的包

4 使用C編寫並鏈接到python解釋器的內置模塊

 

a. import語句

python 內置了很多模塊,比如ossystime等,也可以是自定義模塊、模塊包、C擴展等,使用import無法區分導入的模塊類型

import 模塊名      

例如:導入spam.py

import spam(不含.py

導入多個模塊:

import os,time,sys

 

模塊可以包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行(import語句是可以在程序中的任意位置使用的,且針對同一個模塊import很多次,爲了防止你重複導入,python的優化手段是:第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載大內存中的模塊對象增加了一次引用,不會重新執行模塊內的語句)

 

每個模塊都是一個獨立的名稱空間,定義在這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊中全局變量會在被導入時,與使用者的全局變量衝突

 

導入模塊幹了哪些事:
1 執行源文件
2 以一個源文件的全局名稱空間
3 在當前位置拿到一個模塊名,指向2創建的名稱空間

#測試一:money與spam.money不衝突
#test.py
import spam
money=10
print(spam.money)

輸出:
from the spam.py
1000
 
#測試二:read1與spam.read1不衝突
#test.py
import spam
def read1():
     print('========')
spam.read1()

輸出:
from the spam.py
spam->read1->money1000

#測試三:執行spam.change()操作的全局變量money仍然是spam中的
#test.py
import spam
money=1
spam.change()
print(money)

輸出:
from the spam.py
1

 

模塊別名功能


練習:

有兩鍾sql模塊mysqloracle,根據用戶的輸入,選擇不同的sql功能

#mysql.py
def sqlparse():
    print('from mysql sqlparse')
 
#oracle.py
def sqlparse():
    print('from oracle sqlparse')
 
#test.py
db_type=input('>>: ')
if db_type == 'mysql':
    import mysql as db
elif db_type == 'oracle':
    import oracle as db
 
db.sqlparse()

 

        爲已經導入的模塊起別名的方式對編寫可擴展的代碼很有用,假設有兩個模塊xmlreader.pycsvreader.py,它們都定義了函數read_data(filename):用來從文件中讀取一些數據,但採用不同的輸入格式。可以編寫代碼來選擇性地挑選讀取模塊

if file_format == 'xml':
    import xmlreader asreader
elif file_format == 'csv':
    import csvreader asreader
data=reader.read_date(filename)


 

b. from…import語句

from 模塊名  import 模塊名中的方法

例如:from spamimport money,read1,read2,change

 

如果模塊中的方法太多,可以使用:

from spam import  *     (不推薦使用,容易與執行文件的命名空間衝突)

__all__=['money','x']      #from spam import * 有用,之後導入moneyx方法
_money=1000             #from spam import * 有用,不會導入這個方法

 

對比import spam,會將源文件的名稱空間'spam'帶到當前名稱空間中,使用時必須是spam.名字的方式,而from 語句相當於import,也會創建新的名稱空間,但是將spam中的名字直接導入到當前的名稱空間中,在當前名稱空間中,直接使用名字就可以了

#spam.py
print('from the spam.py')

money=0
def read1():
    print('spam->read1->money',money)

def read2():
    print('spam->read2 calling read')
    read1()

def change():
    global money
    money=0 
 
# 執行文件
from spam import money,read1,read2,change
money=0
print(money)
print(read1)

輸出:
from the spam.py                    #首先執行spam.py
0                      #仍然是當前執行文件的命名空間中的money
<function read1 at 0x00000000026DE950>

優點:使用源文件內的名字時無需加前綴,使用方便

缺點:容易與當前文件的名稱空間內的名字混淆

 

c. 模塊搜索路徑

模塊只在第一次導入時纔會執行,之後的導入都是直接引用內存已經存在的結果
import sys
print('spam' in sys.modules)            #存放的是已經加載到內的模塊

注意:自定義的模塊名一定不要與python自帶的模塊名重名

模塊的查找順序是:內存中已經加載的模塊->內置模塊->sys.path路徑中包含的模塊

import time
import importlib

import spam           #導入模塊會把硬盤中的模塊內容加載到內存中
time.sleep(20)
import spam           #再次導入會直接從內存中查找,忽略硬盤中模塊內容
print(spam.money)
importlib.reload(spam)         #會重新加載模塊(只在測試環境使用)
print(spam.money)

 

import sys

print(sys.path)              #模塊的搜索路徑

sys.path從以下位置初始化

    1  執行文件所在的當前目錄

    2  PTYHONPATH(包含一系列目錄名,與shell變量PATH語法一樣)

    3  依賴安裝時默認指定的

加入模塊路徑:

import sys
print(sys.path)
sys.path.insert(0,r'要添加的模塊路徑')       #插入模塊路徑
sys.path.append(r'要添加的模塊路徑')         #追加模塊路徑


 

d. 區分python文件的兩種用途

文件當做腳本(執行文件)運行時__name__等於__main__
文件當做模塊被加載運行時__name__等於模塊名

# m1.py
import os,sys
x=1
def func1():
    print('from m1')
def func2():
    print('from m2')
def func3():
    print('from m3')
# print(__name__)
#文件當做腳本運行時__name__等於__main__
#文件當做模塊被加載運行時__name__等於模塊名
if __name__ == '__main__':
    #當做腳本使用時才執行
    func1()
    func2()
    func3() 
# run.py
 
import m1            #導入m1模塊
m1.func3()

 

e.

python3中創建文件夾會自動創建__init__.py

python2中創建包需要手動創建__init__.py

. 無論是import形式還是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包纔有的導入語法

2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)

3. import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件

強調:

 1. python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯

 2. 創建包的目的不是爲了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包即模塊

    3.凡是在導入時帶點的,點的左邊都必須是一個包


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章