文章目錄
三大神器之三:生成器
1. 什麼是生成器
生成器就是迭代器中的一種
生成器作爲容器,存儲的不是數據,而是產生數據的算法
取數據的特點和迭代器一樣
當數據龐大時,生成器特別省內存
2. 怎麼創建生成器
調用帶有 yield 關鍵字的函數,就可以得到一個生成器
yield關鍵字只能用在函數體中
def func1():
print('111')
if False:
yield
re = func1()
print(re) # 結果是一個生成器
上面這樣寫很不推薦,但是這裏說明一個問題:
函數中只要有yield,不管遇不遇得到,調用這個函數都不會執行函數體,並且得到的是一個生成器對象
3. 生成器怎麼產生數據
即如何確定生成器中的元素
一個生成器能夠產生多少個數據和哪些數據,看執行完生成器關聯的函數的函數體會遇到幾次yield,yield後面的值就是每次生成的元素
def func2():
print('111')
yield 10
print('222')
yield 100
yield 1000
gen1 = func2()
for x in gen1:
print(x)
結果:
111
10
222
100
1000
4. 生成器產生數據的規律
獲取第一個元素的時候,從函數體的第一條語句開始執行,一直執行到第一個yield,暫停函數執行,並且返回當前獲取到的元素
獲取下一個元素的時候,接着上次暫停的位置開始往後執行,直到遇到下一個yield,暫停函數執行,並且返回當前獲取到的元素
依次類推
從執行位置開始,到函數結束,如果沒有遇到yield,報StopIteration 的錯誤
def func3(n):
for x in range(1, n+1):
yield x * x
gen3 = func3(5)
for i in gen3:
print(i)
結果:
1
4
9
16
25
隨堂練習:
寫一個生成器,能夠產生一班所有學生學號,班級人數自定
def creat_stu_num(pre: str, n: int):
for i in range(1, 10 ** n):
num = str(i).zfill(n)
tar = pre + num
yield tar
n是班級人數的最大數位,若是100人一下的班級,輸入2;1000人以下,輸入3
生成式
1. 什麼是生成式
生成式本質是生成器,只是寫法上更簡潔,只有一行代碼
寫法 | 相當於 |
---|---|
生成器 = (表達式 for 變量 in 序列) | def 函數名() for 變量 in 序列: yield 表達式 生成器 = 函數名() |
def creat_num():
for num in range(1, 11):
yield num * 2
gen1 = creat_num
# 效果等同的生成式:
gen2 = (x * 2 for x in range(1, 11))
寫法 | 相當於 |
---|---|
生成器 = (表達式 for 變量 in 序列 if 條件語句) | def 函數名() for 變量 in 序列: if 條件語句: yield 表達式 生成器 = 函數名() |
生成器 = (表達式 for 變量1 in 序列1 for 變量2 in 序列2) | def 函數名() for 變量1 in 序列1: for 變量2 in 序列2: yield 表達式 生成器 = 函數名() |
隨堂練習:
口算出生成器中的元素
gen4 = (x for x in range(0, 10) if x % 2)
答案:1, 3, 5, 7, 9
2. 列表生成式
將上面生成式語法中的小括號變成中括號,結果就會由原來的生成器變成列表
相當於: list(生成器)
模塊
1. 什麼是模塊
python中,一個.py文件就是一個模塊
2. 導入模塊
如果想要在一個模塊中使用另一個模塊中的內容,需要在當前模塊中導入另外的模塊
1) 怎麼導
a. import 模塊名
導入後可以使用被導入模塊中的所有全局變量(包括普通的全局變量、函數、類等)
以模塊名.變量名的方式去使用模塊中的內容
import math
print(math.cos(math.pi)) # -1.0
導入多個模塊時,一般系統的放前面,第三方的放中間,自己的放最後
b. from 模塊名 import 變量1, 變量2, 變量3…
導入後,只能使用import後指定的全局變量
使用的時候直接用即可,不需要用模塊名.變量名的形式
from math import cos, pi
print(cos(pi)) # -1.0
c. from 模塊名 import *
* - 通配符,表示所有
導入模塊中的所有全局變量,使用的時候直接用即可
from math import *
print(cos(pi)) # -1.0
d. as 重命名
可以對模塊進行重命名
import math as m
print(m.cos(m.pi)) # -1.0
也可以對模塊中的全局變量重命名
from math import cos as c, pi as p
print(c(p)) # -1.0
3. 導入模塊的原理
import 一個模塊時,會把這個模塊的所有代碼從頭到尾執行完,執行完後,回到當前模塊接着往後執行
不管是哪種方式import的模塊或者模塊中的變量
4. 阻止導入模塊的部分代碼段
將需要阻止被導入的代碼段放到下面的if格式裏:
if __name__ == '__main__':
print('1111111')
上面打印’1111111’的語句在if語句裏面,在當前模塊裏可以執行,當別的模塊導入此模塊時,不會執行裏面的代碼段
原理:
在創建模塊的時候,系統會自動給這個模塊添加__name__屬性,用來保存當前模塊的名字,__name__屬性的值默認是模塊的文件名(不含擴展名)
直接運行這個模塊的時候,__name__的屬性值會臨時變成’__main__’,運行完之後又變回文件名
即:當前運行(Run)的模塊的__name__是’__main__’,其他時候都是文件名
包(Package)
包含__init__.py文件的文件夾;用來管理模塊的
導入包中的模塊:
a. 直接用import導
import http.client as cl
b. 用from導
from http import client
c. 直接導入包
import http
import包時,__init__總會執行,自創的包得把導入模塊的語句寫到__init__.py文件中
__init__.py的基本用法:
a. 導入這個包中的相關的所有模塊
import game.display
import game.font
import game.image
b. 給包中的模塊,或者模塊中的變量創建快捷方式
bg = game.display.bg
c. 可以封裝一些通用的方法、函數
def......
hashlib的使用
主要用來對信息加密的
不可逆加密
1. 什麼是hashlib
hashlib是python提供的用來通過哈希算法進行加密(產生摘要)的的一個庫
哈希算法又叫離散算法,主要包含兩種常用的算法:
md5、sha
2. hash算法加密的特點
- 加密後的摘要(密文)是不可逆的
即無法根據密文反推出原文
-
相同數據通過同一種算法產生的摘要相同
-
不同長度的數據通過同一種算法產生的摘要的長度是一樣的
3. 產生數據的摘要
- 創建hashlib的對象
hashlib.算法名()
hash = hashlib.md5()
- 添加數據
哈希對象.update(數據)
數據要求:必須是二進制數據
若需加密數據,則需要先轉換二進制
python中的bytes就是二進制對應的數據類型
python中的字符串轉二進制:
bytes(字符串, encoding=‘utf-8’)
字符串.encode() # 這裏默認用utf-8編碼
python中的二進制轉字符串:
str(二進制, encoding=‘utf-8’)
二進制.decode(encoding=‘utf-8’)
password = '123456'
hash.update(password.encode())
- 生成摘要(密文)
result = hash.hexdigest()
print(result)
全部過程串起來:
import hashlib as hl
hash1 = hl.md5()
password = '123456'
hash1.update(password.encode())
result = hash1.hexdigest()
print(result) # e10adc3949ba59abbe56e057f20f883e
作業
-
寫一個生成式能夠產生的數據爲: 1, 4, 27, 256, 3125,…, 9**9
a = [x ** x for x in range(1, 10)]
-
寫一個生成式能夠產生1-10中所有半徑是偶數的圓的面積
import math as m b = [m.pi * (r ** 2) for r in range(1, 11) if r & 1 == 0]
-
寫一個生成式交換字典的鍵和值,產生一個新的字典
dict1 = {'1': 2, '2': 3} c = dict((v, k) for k, v in dict1.items())
爲了代碼簡單易懂用了items,雖然老師強烈反對用items,因爲效率低