我的Python學習筆記_Day12 三大神器之生成器、模塊、包

三大神器之三:生成器

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算法加密的特點

  1. 加密後的摘要(密文)是不可逆的

​ 即無法根據密文反推出原文

  1. 相同數據通過同一種算法產生的摘要相同

  2. 不同長度的數據通過同一種算法產生的摘要的長度是一樣的

3. 產生數據的摘要

  1. 創建hashlib的對象

hashlib.算法名()

hash = hashlib.md5()
  1. 添加數據

哈希對象.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())
  1. 生成摘要(密文)
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. 寫一個生成式能夠產生的數據爲: 1, 4, 27, 256, 3125,…, 9**9

    a = [x ** x for x in range(1, 10)]
    
  2. 寫一個生成式能夠產生1-10中所有半徑是偶數的圓的面積

    import math as m
    b = [m.pi * (r ** 2) for r in range(1, 11) if r & 1 == 0]
    
  3. 寫一個生成式交換字典的鍵和值,產生一個新的字典

    dict1 = {'1': 2, '2': 3}
    c = dict((v, k) for k, v in dict1.items())
    

    爲了代碼簡單易懂用了items,雖然老師強烈反對用items,因爲效率低

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