模塊
一、模塊基礎(chǔ)
1、概述
-
命名空間
由于在Python中一切皆為對象(Object), 想要好好理解Module和Package,一定要先理解Namespace的概念。 所謂Namespace,是指標示符的可見范圍。對于Python而言,常見的Namespace主要有以下幾種
- Build-in Namespace (內(nèi)建命名空間)
- Global Namespace (全局命名空間)
- Local Namespace (局部命名空間)
有了命名空間的概念,可以有效的解決函數(shù)或者是變量重名的問題。不同的命名空間中允許出現(xiàn)相同的函數(shù)名或者 是變量名。它們彼此之間不會相互影響,例如在Namespace A和B中同時有一個名為var的變量,對A.var賦值并不 會改變B.var的值。
-
為什么使用模塊?
在計算機程序的開發(fā)過程中,隨著程序代碼越寫越多,在一個文件里代碼就會越來越長,越來越難以維護
-
模塊概述
為了編寫可維護性的代碼,我們會把很多函數(shù)進行分組,分別放到不同的文件里去。這樣,每個文件包含的代碼就相對較少,大多數(shù)編程語言都是采用這種方式來組織代碼的,在python中,一個.py文件就稱之為一個模塊
Python中的一個Module對應(yīng)的就是一個.py文件。其中定義的所有函數(shù)或者是變量都屬于這個Module。這個Module 對于所有函數(shù)而言就相當于一個全局的命名空間。而每個函數(shù)又都有自己局部的命名空間。
-
優(yōu)點
- 提高了代碼的可維護性
- 提高了代碼的復用度,編寫代碼不必從零開始,當一個模塊編寫完成,就可以在其他地方引用
- 引用其他模塊,包含python內(nèi)置模塊和第三方模塊
- 避免函數(shù)名和變量名等命名的沖突
-
模塊分類
標準庫模塊
第三方模塊
自定義模塊
2、使用標準庫中的模塊
-
time
import time now = time.strftime("%Y-%m-%d %H:%M:%S") # 獲取當前時間 print(now) -
random
import random random_num = random.randrange(3) # 返回012的隨機數(shù) print(random_num)
3、使用自定義模塊
-
新建一個名為speak.py文件
# speak.py ''' This is only a test module ''' name = 'lucky' age = 18 def speak(): print("lucky is a very good man!") -
import 語句
-
作用
導入模塊/包
-
格式
import module1[, module2[, module3[, ……]]]
import module1 as 別名[, module2[, module3[, ……]]] 起別名
-
注意
一個模塊只會被導入一次,不管你執(zhí)行了多少次import,有效的防止導入模塊被一次次的執(zhí)行
-
使用模塊中的內(nèi)容
module.方法/類/變量
不起別名實例
import speak # 導入speak模塊 >>> speak.name # 獲取模塊speak中name的值 lucky >>> speak.age # 獲取模塊speak中age的值 18 >>> speak.speak() # 調(diào)用模塊中speak方法 lucky is a very good man! >>> print speak.__doc__ # 獲取模塊說明 This is only a test module起別名實例
>>> import speak as s # 導入speak模塊 并起別名為s >>> s.name # 獲取模塊speak中name的值 lucky >>> s.age # 獲取模塊speak中age的值 18 >>> s.speak() # 調(diào)用模塊中speak方法 lucky is a very good man! >>> print s.__doc__ # 獲取模塊說明 This is only a test module -
-
from ... import 語句
-
作用
從模塊中導入一些指定的部分
-
格式
from module import name1[, name2[, name3[, ……]]]
實例
>>> from speak import name,age,speak # 從speak模塊導入 name,age,speak >>> name # 獲取模塊speak中name的值 lucky >>> age # 獲取模塊speak中age的值 18 >>> speak() # 調(diào)用模塊中speak方法 lucky is a very good man! -
-
from ... import * 語句
-
概述
將模塊中所有非下劃線開頭的成員都導入
-
作用
把一個模塊中所有的內(nèi)容全部導入當前命名空間
-
格式
from modulename import *
-
注意
不應(yīng)該過多使用,很可能造成變量名的沖突
實例
>>> from speak import * # 會將speak模塊中非下劃線開頭的成員都導入當前命名空間中 >>> name # 獲取模塊speak中name的值 lucky >>> age # 獲取模塊speak中age的值 18 >>> speak() # 調(diào)用模塊中speak方法 lucky is a very good man! -
4、__all__接口暴露
-
概述
代碼中是不提倡用
from xxx import *的寫法的,但是在 console 調(diào)試的時候圖個方便還是很常見的。如果一個模塊spam沒有定義__all__,執(zhí)行from spam import *的時候會將spam中非下劃線開頭的成員都導入當前命名空間中,這樣當然就有可能弄臟當前命名空間。如果顯式聲明了__all__,import *就只會導入__all__列出的成員。如果__all__定義有誤,列出的成員不存在,還會明確地拋出異常,而不是默默忽略。 -
格式
__all__ = ["name1", "name2"...] -
作用
Python不像 Ruby 或者 Java,Python 沒有語言原生的可見性控制,而是靠一套需要大家自覺遵守的”約定“下工作。比如下劃線開頭的應(yīng)該對外部不可見。同樣,
__all__也是對于模塊公開接口的一種約定,比起下劃線,__all__提供了暴露接口用的”白名單“。一些不以下劃線開頭的變量(比如從其他地方import到當前模塊的成員)可以同樣被排除出去。 -
新建test_all.py
# test_all.py ''' This is only a test __all__ module ''' __all__ = ["name", "speak"] # 排除了 age name = 'lucky' age = 18 def speak(): print("lucky is a very good man!")
5、模塊循環(huán)引用
-
概述
出現(xiàn)循環(huán)引用其實就是模塊之間發(fā)生了相互依賴,A依賴B,B依賴A,這樣他們直接相互依賴,引用的時候就會出現(xiàn)者循環(huán)引用(交叉引用)
-
現(xiàn)象
有兩個模塊moduleA 和 moduleB
moduleA.py
from moduleB import b def a(): print('我是A模塊的a方法') moduleB.b() def c(): print('我是A模塊的c方法') if __name__ == '__main__': a()moduleB.py
from moduleA import c def b(): print('我是B模塊的b方法') c() -
導入的實質(zhì)
導入其實是要將 被導入模塊所有的頂格代碼都執(zhí)行一遍,遇到函數(shù)和類的定義會作申明
如果b模塊中有這么一句print('我是B模塊')你在a模塊impot b時就會 執(zhí)行 print('bbb')這一句
回到循環(huán)引用中,首先導入B,進入B中,發(fā)現(xiàn)B中又導入了A又回到A中,但是A又導入B這就形成了循環(huán)引用
-
解決方式1(直接導入模塊名,通過模塊調(diào)用其中的函數(shù))
moduleA.py
import moduleB def a(): print('我是A模塊的a方法') moduleB.b() def c(): print('我是A模塊的c方法') if __name__ == '__main__': a()moduleB.py
import moduleA def b(): print('我是B模塊的b方法') moduleA.c() if __name__ == '__main__': b() -
解決方式2(使用延遲導入(lazy import))
內(nèi)部導入
""" moduleB.py """ def b(): from moduleA import c print('我是B模塊的b方法') c()
6、__name__屬性
-
概述
每個模塊都有一個name屬性,當其值為“main”時表明該模塊自身在運行,否則是被當做模塊導入,此時值為模塊的名字
-
實例
# speak.py ''' This is only a test module ''' name = 'lucky' age = 18 def speak(): print("lucky is a very good man!") if __name__ == '__main__': speak() -
__name__作用模塊就是一個可執(zhí)行的python文件,一個模塊被另一個模塊導入,想讓模塊中的某一段代碼不執(zhí)行,可以使用
__name__屬性來使程序隱藏該段代碼,當自身執(zhí)行時在執(zhí)行該塊代碼。一般作為判斷是否是作為主運行文件 -
擴展
以后主要用于程序入口使用(項目啟動文件中使用)
"""
Main.py
"""
def main():
pass
if __name__ == '__main__':
main()
7、包
-
需求
如果不同的人編寫的模塊名相同怎么辦?
-
解決
為了避免模塊名的沖突,python又引入了按目錄來組織模塊的方法,稱為包(package)
-
特點
引入包以后,只要頂層包名不與別人沖突, 那么所有的模塊都不會與別人沖突
-
注意
每個包目錄下都會有一個名為
__init__.py的文件,說明這個目錄是個python包,還可以導出包中的內(nèi)容 -
建包
新建文件夾名稱為lucky_package文件夾
目錄結(jié)構(gòu)
project/ lucky_package/ __init__.py # 聲明lucky_package為一個包 speak.py # 模塊speak test.py # 用于測試lucky_package包的使用實現(xiàn)
-
方式一 通過pycharm直接創(chuàng)建Python包
選擇模塊 -> New -> Python Package
-

輸入包名

點擊OK

-
方式二 手動創(chuàng)建
- 模塊 -> New -> Directory

- 輸入 lucky_package

- 點擊OK

- lucky_package -> New -> Python File

- 輸入文件名稱為 `__init__.py`

- 點擊 OK

-
包內(nèi)創(chuàng)建模塊
speak.py
# speak.py ''' This is only a test module ''' name = 'lucky' age = 18 def speak(): print("lucky is a very good man!") if __name__ == '__main__': speak() -
使用
test.py
-
第一種導入方式使用
>>> from lucky_package import speak # 從lucky_package包導入speak模塊 >>> speak.name # 獲取模塊speak中name的值 lucky >>> speak.age # 獲取模塊speak中age的值 18 >>> speak.speak() # 調(diào)用模塊中speak方法 lucky is a very good man!導包重命名
>>> from lucky_package import speak as s # 從lucky_package包導入speak模塊并重命名為s >>> s.name # 獲取模塊speak中name的值 lucky -
第二種導入方式
>>> from lucky_package.speak import name,age,speak # 從lucky_package包speak模塊導入 name,age,speak >>> name # 獲取模塊speak中name的值 lucky >>> age # 獲取模塊speak中age的值 18 -
第三種導入方式
>>> from lucky_package.speak import * # 從lucky_package包speak模塊導入 所有成員 >>> name # 獲取模塊speak中name的值 lucky >>> age # 獲取模塊speak中age的值 18 -
第四種導入方式
>>> import lucky_package.speak # 導入lucky_package里speak包 >>> lucky_package.speak.name # 獲取name的值 lucky -
第五種導入方式
>>> import lucky_package.speak as s # 導入lucky_package里speak包 >>> s.name # 獲取name的值 lucky
-
-
填充包
__init__.py代碼-
方式一 在init.py中 導入模塊
__init__.pyfrom . import speak使用
>>> from lucky_package import speak # 導入lucky_package里speak包 >>> speak.name # 獲取name的值 lucky -
方式二
在init.py中 導入模塊所有成員
__init__.pyfrom .speak import *使用
>>> from lucky_package import * # 導入lucky_package里speak包 >>> name # 獲取name的值 lucky -
注意
不建議這樣使用方式
-
二、常用模塊
1、time模塊
-
名詞
UTC(世界協(xié)調(diào)時間):格林尼治時間,世界標準時間,北京時間1970年01月01日08時00分00秒)起至現(xiàn)在的總秒數(shù),在中國為UTC+8DST(夏令時):是一種為了節(jié)約能源而人為規(guī)定地方時間的制度,一般在天亮早的夏季將時間提前一小時
-
時間的表示形式
時間戳
以整型或浮點型表示的是一個以秒為單位的時間間隔,這個時間的基礎(chǔ)值是1970年1月1號零時開始算元組
一種python的數(shù)據(jù)結(jié)構(gòu)表示方式,這個元組有9個整數(shù)元素,分別表示不同的時間含義
year 年
month(1-12) 月
day(1-31) 日
hours(0-23) 時
minutes(0-59) 分
seconds(0-59) 秒
weekday(0-6,0表示星期一) 周
Julian day(1-366):表示當前日期在本年度是第幾天
DST flag(-1 or 0 or 1):夏令時格式,0表示正常格式,1表示夏令時格式,-1表示根據(jù)當前的時間格式來判定導入
import time
-
格式化日期的函數(shù)
| 函數(shù) | 函數(shù)說明 |
| :-------------------------------------------------------- | ------------------------------------------------------------ |
| time.time() | 當前時間戳(秒數(shù)) UNIX和Windows只支持到2038年。 |
| time.localtime() | 接收時間輟(1970紀元后經(jīng)過的浮點秒數(shù))并返回當?shù)貢r間下的時間元組 (0是周一) |
| time.strftime("%Y-%m-%d %H:%M:%S") | 函數(shù)接收以時間元組,并返回以可讀字符串表示的當?shù)貢r間,格式由參數(shù) format 決定。第二個參數(shù)可有可無 |
| time.asctime() | 返回格式化后的英文文本的時間 |
| time.mktime(tupletime) | 接受時間元組并返回時間輟 |
| time.sleep(secs) | 推遲調(diào)用線程的運行,secs指秒數(shù)。 |
| time.clock() | 用以浮點數(shù)計算的秒數(shù)返回當前的CPU時間。用來衡量不同程序的耗時,比time.time()更有用。 |
| time.strptime("2013-10-10 23:40:00", "%Y-%m-%d %H:%M:%S") | 將給定時間轉(zhuǎn)換為時間元組 | -
時間日期格式化符號
符號 說明 符號 說明 %Y 4位的年 %y 2位的年 %m 月份(01-12) %d 月內(nèi)中的一天(0-31) %H 24小時制小時數(shù)(0-23) %I 12小時制小時數(shù)(01-12) %M 分鐘數(shù)(00=59) %S 秒(00-59) %a 本地簡化星期名稱 英文文本 簡化 %A c本地簡化星期名稱 英文文本 完整 %j 年內(nèi)的一天(001-366) %w 星期(0-6),星期天為星期的開始 (0是周一) %x 本地相應(yīng)的日期表示 (08/02/17) %X 本地相應(yīng)的時間表示 23:48:34 -
time()
返回當前時間的時間戳,無需參數(shù),返回值為浮點型
t1 = time.time() print(t1) -
localtime([t])
將給定的時間戳轉(zhuǎn)為本地時間元組格式,如果沒有參數(shù)默認轉(zhuǎn)換當前時間戳
t3 = time.localtime() print(t3) -
mktime(tt)
將本地時間元組轉(zhuǎn)為時間戳
t4 = time.mktime(t3) print(t4) import time t = (2016, 2, 17, 17, 3, 38, 1, 48, 0) secs = time.mktime( t ) print ("time.mktime(t) : %f" % secs)#time.mktime(t) : 1455699818.000000 time.strptime(“2013-10-10 23:40:00”, "%Y-%m-%d %H:%M:%S") time = time.mktime(time.strptime("2013-10-10 23:40:00", "%Y-%m-%d %H:%M:%S")) print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time))) -
asctime([tt])
將時間元組格式轉(zhuǎn)為指定格式的字符串形式,如果沒有參數(shù)默認使用localtime時間的時間元組
t5 = time.asctime(t3) print(t5, type(t5)) -
strftime(format[, tt])
將時間元組以指定的格式轉(zhuǎn)為字符串,如果沒有tt參數(shù)默認使用當前本地時間元組
t7 = time.strftime("%Y-%m-%d %H:%M:%S", t3) print(t7) -
strptime(st, format)
將指定格式的字符串解析為時間元組,是strftime的逆過程
注意:format表示的格式要與st一致
t8 = time.strptime("2001-10-01 08:08:08", "%Y-%m-%d %H:%M:%S") print(t8) -
sleep()
延遲一個時間段,接收整型或者浮點型
time.sleep(2) -
clock()
返回當前程序執(zhí)行時間,Unix系統(tǒng)始終返回全部運行時間,而Windows系統(tǒng)從第二次開始都是以第一次調(diào)用此函數(shù)的時間戳為基準,而不是以程序開始的時間為基準
# windows Unix print(time.clock()) # 0 1 time.sleep(1) print(time.clock()) # 1 2 time.sleep(1) print(time.clock()) # 2 3 -
案例
計算程序運行時間
import time def procedure(): for i in range(10000): pass # time.clock t0 = time.clock() procedure() print (time.clock() - t0) # time.time t0 = time.time() procedure() print (time.time() - t0)計算一個人活了多久
import time # 將其轉(zhuǎn)換為時間元組 time_tup = time.strptime("1993-10-10 23:40:00", "%Y-%m-%d %H:%M:%S") before_time = time.mktime(time_tup) # 根據(jù)實際元組返回秒數(shù) now_time = time.time() - before_time print(now_time/60/60,'小時') print(now_time/60/60/24,'天') print(now_time/60/60/24/365,'年') print(round(now_time/60/60/24/365, 2),'年')
2、datetime模塊
- 概述
datetime比time高級,可以理解為datetime基于time進行了封裝,提供了更簡單的函數(shù)接口,datetime模塊的接口更直觀、更容易調(diào)用
-
模塊中的類
- time 只關(guān)注時間
- date 只關(guān)注日期
- datetime 同時關(guān)注日期和時間
- timedelta 主要用于計算時間跨度
- tzinfo 時區(qū)相關(guān)
-
導入
import datetime -
方法
-
獲取當前時間
t1 = datetime.datetime.now() print(t1, type(t1)) -
獲取指定日期時間
t2 = datetime.datetime(2001, 10, 1, 8, 8, 8) print(t2) -
將datetime時間轉(zhuǎn)對象為字符串
t3 = t1.strftime("%X %x") print(t3, type(t3)) -
將字符串轉(zhuǎn)為datetime對象
t4 = datetime.datetime.strptime(t3, "%X %x") print(t4, type(t4)) -
時間相減,返回一個時間間隔
t5 = datetime.datetime(2001, 10, 1, 8, 8, 8) t6 = datetime.datetime(2001, 10, 2, 9, 8, 9) t7 = t6- t5 print(t7, type(t7)) #獲取時間間隔天數(shù) print(t7.days) #獲取去除間隔天數(shù)以外的間隔秒數(shù) print(t7.seconds) -
Python 獲取昨天日期
# 引入 datetime 模塊 import datetime def getYesterday(): today=datetime.date.today() oneday=datetime.timedelta(days=1) yesterday=today-oneday return yesterday # 輸出 print(getYesterday())
-
3、calendar模塊
-
概述
日歷模塊
-
導入
import calendar -
方法
-
返回指定年的某月
print(calendar.month(2019, 2)) 返回指定年的日歷
print(calendar.calendar(2018))-
判斷是否是閏年
print(calendar.isleap(2000)) -
返回某個月的weekday的第一天和這個月的所有天數(shù)
print(calendar.monthrange(2019, 4)) -
返回某一個月以一周為周期的元素序列
print(calendar.monthcalendar(2019, 2))
-
4、Pillow模塊
-
概述
PIL:Python Imaging Library,已經(jīng)是Python平臺事實上的圖像處理標準庫了。PIL功能非常強大,但API卻非常簡單易用。
由于PIL僅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基礎(chǔ)上創(chuàng)建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了許多新特性,因此,我們可以直接安裝使用Pillow。
-
安裝Pillow
如果安裝了Anaconda,Pillow就已經(jīng)可用了。否則,需要在命令行下通過pip安裝:
$ pip install pillow如果遇到
Permission denied安裝失敗,請加上sudo重試。- 操作圖像
來看看最常見的圖像縮放操作,只需三四行代碼:
from PIL import Image # 打開一個jpg圖像文件,注意是當前路徑: im = Image.open('test.jpg') # 獲得圖像尺寸: w, h = im.size print('Original image size: %sx%s' % (w, h)) # 縮放到50%: im.thumbnail((w//2, h//2)) print('Resize image to: %sx%s' % (w//2, h//2)) # 把縮放后的圖像用jpeg格式保存: im.save('thumbnail.jpg', 'jpeg')其他功能如切片、旋轉(zhuǎn)、濾鏡、輸出文字、調(diào)色板等一應(yīng)俱全。
比如,模糊效果也只需幾行代碼:
from PIL import Image, ImageFilter # 打開一個jpg圖像文件,注意是當前路徑: im = Image.open('test.jpg') # 應(yīng)用模糊濾鏡: im2 = im.filter(ImageFilter.BLUR) im2.save('blur.jpg', 'jpeg')驗證碼實現(xiàn)
from PIL import Image, ImageDraw, ImageFont, ImageFilter import random # 隨機字母: def rndChar(): return chr(random.randint(65, 90)) # 隨機顏色1: def rndColor(): return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) # 隨機顏色2: def rndColor2(): return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) # 240 x 60: width = 60 * 4 height = 60 image = Image.new('RGB', (width, height), (255, 255, 255)) # 創(chuàng)建Font對象: # windwos下 font = ImageFont.truetype(r'C:\Windows\Fonts/Arial.ttf', 36) # Mac下 # font = ImageFont.truetype('Arial.ttf', 36) # 創(chuàng)建Draw對象: draw = ImageDraw.Draw(image) # 填充每個像素: for x in range(width): for y in range(height): draw.point((x, y), fill=rndColor()) # 輸出文字: for t in range(4): draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2()) # 模糊: image = image.filter(ImageFilter.BLUR) image.save('code.jpg', 'jpeg')作業(yè):自己寫一個實現(xiàn)等比縮放的函數(shù)
4、uuid模塊
-
概述
是128位的全局唯一標識符,通常由32字節(jié)的字母串表示,它可以保證時間和空間的唯一性,也稱為GUID
-
作用
隨機生成字符串,在token、賬號、訂單號等需要唯一標識的地方使用
-
原理
通過Mac地址、時間戳、命名空間、隨機數(shù)、偽隨機數(shù)來保證產(chǎn)生的id的唯一性
-
算法:
uuid1()基于時間戳
有MAC地址、當前時間戳、隨機數(shù)字,可以保證全球范圍內(nèi)的唯一性。但是由于MAC地址的使用會帶來安全問題,局域網(wǎng)中可以使用IP來代替MAC-
uuid2()基于分布式計算環(huán)境DCE
算法和uuid1()相同,不同的是把時間戳的前4位換成POSI的UID,實際當中很少使用注意:python中沒有這個函數(shù)
uuid3()基于名字和MD5散列值
通過計算名和命名空間的MD5散列值得到,保證了同一命名空間中不同名字的唯一性,和不同命名空間的唯一性,但是同一命名空間的相同名字生成相同的uuiduuid4()基于隨機數(shù)
由偽隨機數(shù)得到的,有一定的重復概率,這個重復概率是可以通過計算得到的uuid5()基于名字和SHA1散列值
算法和uuid3()相同,不同的是使用SHA1算法
-
使用經(jīng)驗:
- python中沒有基于DCE的,所以uuid2()可以忽略
- uuid4()存儲概率性重復,由于無映射性所以最好不用
- 如果在全局的分布式環(huán)境下,最好使用uuid1()
- 若名字的唯一性要求,最好使用uuid3()或者uuid5()
-
導入
import uuid -
使用
a = uuid.uuid1() print(a, type(a)) b = str(a) print(b, type(b)) # print(uuid.uuid2()) print(uuid.uuid3(uuid.NAMESPACE_DNS, "lucky")) print(uuid.uuid3(uuid.NAMESPACE_DNS, "lucky")) print(uuid.uuid3(uuid.NAMESPACE_OID, "lucky")) print(uuid.uuid3(uuid.NAMESPACE_DNS, "lucky")) print(uuid.uuid5(uuid.NAMESPACE_DNS, "lucky"))
5、collections模塊
-
概述
python中內(nèi)建的一個集合模塊,提供了許多有用的集合類
-
namedtuple
-
概述
命名元組,本質(zhì)是一個函數(shù),用他來創(chuàng)建一個自定義的tuple類型
規(guī)定tuple元素的格式,并可以用屬性而不是索引引用tuple中的元素
用namedtuple實際上是創(chuàng)建一個新的數(shù)據(jù)類型
-
導入
from collections import namedtuple -
使用
#假設(shè)這是一個點的坐標,但是沒有寫注釋,時間久了就忘了該有含義 p = (1, 2) # 定義一個新的數(shù)據(jù)類型, Point = namedtuple("point", ["x", "y"]) # 定義一個Point類型的變量,保存一個元組數(shù)據(jù) p2 = Point(1, 2) print(p2, isinstance(p2, Point), isinstance(p2, tuple)) #訪問命名元組元素的值 print(p2[0], p2[1]) print(p2.x, p2.y)
-
-
deque
-
概述
使用list存儲數(shù)據(jù),按索引訪問元素,但是插入和刪除元素會根據(jù)元素的個數(shù)增多個降低效率。因為list是線性存儲,數(shù)據(jù)量大插入和刪除的效率就會低。
deque就是為了高效實現(xiàn)插入和刪除操作的雙向列表,適用于隊列和棧。并且deque是線程安全的
-
導入
from collections import deque -
使用
q = deque([1,2,3,4,5]) q.append(6) q.appendleft(0) print(q.pop()) print(q.popleft()) print(q)
-
-
defaultdict
-
概述
使用dict時,如果引用的key不存在,如果使用的[]方式則會報KeyError異常,如果使用的get()方式則會得到None。
如果希望key不存在時也能得到一個默認的值就使用defaultdict -
導入
from collections import defaultdict -
使用
d1 = {"a": 1, "b": 2, "c": 3} # print(d1["d"]) # print(d1.get("d")) d2 = defaultdict(lambda :"鍵值對不存在") d2["a"] = 1 d2["b"] = 2 print(d2["c"]) print(d2.get("c")) print(d2, type(d2), isinstance(d2, dict))
-
-
OrderedDict
-
概述
使用dict是,key是無序的。對dict做迭代時無法保證key的順序。如果需要key有順序,就可以使用OrderDict
-
導入
from collections import OrderedDict -
使用
d1 = {"a": 1, "b": 2, "c": 3} for key in d1: print(key) print("----------------------") d2 = OrderedDict([("a", 1),("b", 2),("c", 3)]) print(d2) print(d2["a"]) print(d2.get("b"))
-
-
Counter
-
概述
是一個簡單的計數(shù)器,本質(zhì)上是dict的一個子類
-
導入
from collections import Counter -
使用
需求:計算集合中每個字符出現(xiàn)的次數(shù)
s = "lucky is a good man" c = Counter() print(c, type(c), isinstance(c, dict)) for ch in s: c[ch] = c[ch] + 1 print(c) for key in c: print(key, c[key])
-
6、base64模塊
-
概述
用記事本打開圖片等文件,看到一坨亂碼,因為二進制文件包含很多無法顯示的內(nèi)容。所以想讓記事本能處理二進制數(shù)據(jù),就需要將二進制字符串轉(zhuǎn)換,base64是一種比較常見的二進制編碼方式
-
作用
適用于小段內(nèi)容的編碼,比如數(shù)字證書簽名、cookie、網(wǎng)頁中傳輸?shù)纳倭慷M制數(shù)據(jù)
-
編碼原理
一個包含64個字符的列表
["A", "B", ……, "Z", "a", "b", ……, "z", "0", "1", ……, "9", "+", "/"]
對二進制數(shù)據(jù)進行處理,每是三個字節(jié)一組,一組就是3x8=24bit,劃分為4組,每組正好6bit。得到4個數(shù)字作為索引,然后查表,獲取相應(yīng)的4個字符,就是編碼后的字符串 -
注意
base64是一種通過查表的編碼方法,不能用于加密,即使修改了字符對照表也不行
-
使用
-
b64encode
s1 = b"lucky is a good man" print(base64.b64encode(s1)) s2 = b'c3VuY2sgaXMgYSBnb29kIG1hbg==' print(base64.b64decode(s2))由于=字符也可能出現(xiàn)在base64編碼中,但是=在url、cookie里會造成歧義,所以很多base64編碼會把編碼后的=去掉
s6 = b"abcd" s7 = base64.b64encode(s6) print(s7) ''' 'YWJjZA==' 'YWJjZA' ''' s8 = b'YWJjZA==' print(base64.b64decode(s8))注意
由于標準base64編碼后可能出現(xiàn)字符+或/,在URL中就不能直接作為參數(shù)
-
urlsafe_b64encode
提供urlsafe_b64encode編碼,保證url的安全,將+和/替換為-和_,提供urlsafe_b64decode進行url安全解碼
s3 = b"http://www.xialigang.com" print(base64.urlsafe_b64encode(s3)) s4 = b"aHR0cDovL3d3dy5zdW5jay53YW5n" print(base64.urlsafe_b64decode(s4)) s5 = b"lucky is a good m~" print(base64.b64encode(s5)) print(base64.urlsafe_b64encode(s5))
-
7、hashlib模塊
-
概述
該模塊提供了常見的摘要算法,如MD5、SHA1
摘要算法(又稱哈希算法、散列算法):它通過一個函數(shù),把任意長度的數(shù)據(jù)轉(zhuǎn)為一個長度固定的數(shù)據(jù)串(通常用16進制的字符串表示)
-
作用
用于加密
MD5
最常見的摘要算法,速度快,生成的結(jié)構(gòu)是128位字節(jié),通常用32位16進制字符串表示-
使用
s1 = b"lucky is a good man" m1 = hashlib.md5() m1.update(s1) ret = m1.hexdigest() print(ret) #如果數(shù)據(jù)量比加大,可以分多次調(diào)用update,最終結(jié)果是一樣的 m2 = hashlib.md5() m2.update(b"lucky is a") m2.update(b" good man") ret2 = m2.hexdigest() print(ret2) SHA1
調(diào)用SHA1與調(diào)用MD5完全一樣,SHA1的結(jié)果是160字節(jié),通常用40位16進制字符串表示-
使用
s2 = b"lucky is a good man" sh1 = hashlib.sha1() sh1.update(s2) ret3 = sh1.hexdigest() print(ret3)注意:數(shù)據(jù)量大同md5使用相同
更安全的
SHA256
SHA512
越安全的算法不見越慢,而且摘要越長-
應(yīng)用:
任何允許用戶登錄的網(wǎng)站都會存儲用戶登錄的用戶名和密碼(存儲在數(shù)據(jù)庫中),那么密碼一般存儲的是原密碼的摘要值
lucky-666666明文存儲到數(shù)據(jù)庫中,如果數(shù)據(jù)庫泄露,所有用戶信息就會暴露正確的保存口令方式不是存儲明文,而是存儲口令的摘要,當用戶登錄時,首先計算用戶輸入的明文的摘要,和數(shù)據(jù)庫中的對比,如果一致說明口令正確,否則一定錯誤
8、hmac模塊
-
概述
實現(xiàn)了HMAC算法,是用一個key對數(shù)據(jù)進行“雜湊”后在進行的hash,是用hmac比hash算法更安全,不同的key會產(chǎn)生不同的hash值
-
導入
s = b"lucky is a good man" key = b"good" h = hmac.new(key, s, digestmod="MD5") ret = h.hexdigest() print(ret)
三、第三方模塊
1、安裝
Windows
pip install 模塊名
pip install 模塊名==版本號linux(root用戶)
pip install 模塊名
pip install 模塊名==版本號linux(普通用戶)
sudo pip install 模塊名
sudo pip install 模塊名==版本號-
注意
公司里基本你不會讓你用root用戶
2、卸載
- Windows
pip uninstall 模塊名 - linux(root用戶)
pip uninstall 模塊名 - linux(普通用戶)
sudo pip uninstall 模塊名
3、查看
- 當前所有的三方模塊
pip list - pip的版本
pip --version
4、實際操作
-
pillow
處理圖像
-
安裝
pip install pillow
-
實例
from PIL import Image #打開圖片 im = Image.open("timg.jpg") # 查看圖片信息 print(im.format, im.size, im.mode) #修改圖片大小 im.thumbnail((102, 68)) #生成新圖片 im.save("timg2.jpg", "JPEG")
四、virtualenv虛擬環(huán)境
1、概述
在開發(fā)Python應(yīng)用程序的時候,系統(tǒng)安裝的Python3只有一個版本:3.5。所有第三方的包都會被pip安裝到Python3的site-packages目錄下。
如果我們要同時開發(fā)多個應(yīng)用程序,那這些應(yīng)用程序都會共用一個Python,就是安裝在系統(tǒng)的Python 3。如果應(yīng)用A需要jinja 2.7,而應(yīng)用B需要jinja 2.6怎么辦?
這種情況下,每個應(yīng)用可能需要各自擁有一套“獨立”的Python運行環(huán)境。virtualenv就是用來為一個應(yīng)用創(chuàng)建一套“隔離”的Python運行環(huán)境。
2、安裝
我們用pip安裝virtualenv:
$ pip3 install virtualenv
然后,假定我們要開發(fā)一個新的項目,需要一套獨立的Python運行環(huán)境,可以這么做:
3、操作
- 第一步,創(chuàng)建目錄:
Mac:~ xialigang$ mkdir myproject
Mac:~ xialigang$ cd myproject/
Mac:myproject xialigang$
- 第二步,創(chuàng)建一個獨立的Python運行環(huán)境,命名為
venv:
Mac:myproject xialigang$ virtualenv --no-site-packages venv
Using base prefix '/usr/local/.../Python.framework/Versions/3.4'
New python executable in venv/bin/python3.4
Also creating executable in venv/bin/python
Installing setuptools, pip, wheel...done.
命令virtualenv就可以創(chuàng)建一個獨立的Python運行環(huán)境,我們還加上了參數(shù)--no-site-packages,這樣,已經(jīng)安裝到系統(tǒng)Python環(huán)境中的所有第三方包都不會復制過來,這樣,我們就得到了一個不帶任何第三方包的“干凈”的Python運行環(huán)境。
新建的Python環(huán)境被放到當前目錄下的venv目錄。有了venv這個Python環(huán)境,可以用source進入該環(huán)境:
Mac:myproject xialigang$ source venv/bin/activate
(venv)Mac:myproject xialigang$
注意到命令提示符變了,有個(venv)前綴,表示當前環(huán)境是一個名為venv的Python環(huán)境。
- 安裝各種第三方包,并運行
python命令:
(venv)Mac:myproject xialigang$ pip install jinja2
...
Successfully installed jinja2-2.7.3 markupsafe-0.23
(venv)Mac:myproject xialigang$ python myapp.py
...
在venv環(huán)境下,用pip安裝的包都被安裝到venv這個環(huán)境下,系統(tǒng)Python環(huán)境不受任何影響。也就是說,venv環(huán)境是專門針對myproject這個應(yīng)用創(chuàng)建的。
- 退出當前的
venv環(huán)境,使用deactivate命令:
(venv)Mac:myproject xialigang$ deactivate
Mac:myproject xialigang$
此時就回到了正常的環(huán)境,現(xiàn)在pip或python均是在系統(tǒng)Python環(huán)境下執(zhí)行。
完全可以針對每個應(yīng)用創(chuàng)建獨立的Python運行環(huán)境,這樣就可以對每個應(yīng)用的Python環(huán)境進行隔離。
virtualenv是如何創(chuàng)建“獨立”的Python運行環(huán)境的呢?原理很簡單,就是把系統(tǒng)Python復制一份到virtualenv的環(huán)境,用命令source venv/bin/activate進入一個virtualenv環(huán)境時,virtualenv會修改相關(guān)環(huán)境變量,讓命令python和pip均指向當前的virtualenv環(huán)境。