1. 程式人生 > 其它 >2022.3.24學習筆記

2022.3.24學習筆記

2022.3.24學習筆記

  • 生成器物件(自定義迭代器)
  • 自定義range方法
  • 模組

一、生成器物件

1、概念與結構

概念:本質還是迭代器,只不過是通過自己寫程式碼產生,也有雙下iter和next方法,也是為了節省儲存空間的

結構:

def index():
    print('666')
    yield 123  # yield和return相似,後面跟返回值,可以跟多個

res = index()  # 相當於變身為生成器
res.__next__()  # 呼叫一次生成器,執行生成器程式碼,遇到yield就結束

生成器就是在結構上是函式然後使用yield關鍵字,呼叫方式和迭代器一致,而且生成器與函式相似,但是不能直接呼叫,需要使用迭代器呼叫方法,並且yield與return也有區別,如下:

def index():
    print('666')
    yield 123
    print('777')
    yield 456
    print('888')
    yield 777
注意:使用雙下next方法呼叫一次,相當於函式index執行到yield就結束,在呼叫一次next,再執行一個到yield截至,直到沒有yield為止再取就會報錯,並且yield可以不跟返回值,預設返回None

2、yield關鍵字作用

(1)在函式體程式碼中出現,可以將函式變成生成器

(2)在執行過程中可以將yield後面的值返回去,類似於return,但是不能用變數名接收返回值,只能呼叫

(3)可以暫停程式碼的執行,呼叫一次next方法只能執行到一次yield

(4)還可以接收外界的傳值(瞭解)

# 接收外部傳值舉例
def eat(name):
    print(f'{name}準備乾飯')
    while True:  # 目的是迴圈yield,獲取多個
        food = yield  # 用變數名接收,預設為None,但是yield可以接收外部傳值
        print(f'{name}正在吃{food})
res = eat('jason')  # 變身生成器,並傳參'jason'給name
res.send('蛋糕')  # send可以給內部yield傳值,send必須是在生成器的狀態下呼叫,相當於是給yield傳值並且呼叫一次雙下next方法        

3、生成器表示式

聯想之前的列表字典生成式,為什麼沒有元組生成式,因為這裡表示的是生成器表示式,如下:

res = (i for i in 'jason')  # res就是生成器物件
print(res)  # <generator object <genexpr> at 0x1130cf468>
print(res.__next__())  # j

注意:生成器內部的程式碼只有在呼叫__next__迭代取值的時候才會執行!!

4、生成器面試題!!!

def add(n, i):
    return n + i
def test():
    for i in range(4):
        yield i
g = test()  # 將test函式變成生成器物件
for n in [1, 10]:
    g = (add(n, i) for i in g)
res = list(g)  # list底層就是for迴圈 相當於對g做了迭代取值操作
print(res)
問:最後結果是什麼?
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]
正確答案是C  訣竅就是抓n是多少即可
"""
第一次for迴圈
	g = (add(n, i) for i in g)
第二次for迴圈
	g = (add(10, i) for i in (add(10, i) for i in g))
這時候還沒進行迭代取值g後面的都可以不用看,這就是這道題的關鍵
"""

二、自定義range方法

range方法其實也是一個可迭代物件,所以是否可以藉助生成器物件模擬出range呢?試一試吧

def my_range(start,end = 0,step=1):
    if not end:  # end未傳參,則執行下面程式碼
        end = start  # 重新賦值,保證有頭有尾
        start = 0
    while start < end:
        yield start  # 生成器
        start += step  # 控制步長,預設引數為1

這樣,range方法就被模擬出來了

三、模組

1、模組簡介

(1)什麼是模組?

模組是一系列功能的結合體,可以直接使用

(2)為什麼要用模組?

極大提升開發效率(使用別人寫好的模組當然快啦)

(3)模組的三種來源

1.# 內建模組
無需下載,直譯器自帶,直接匯入即可使用
2.# 自定義模組
自己寫的程式碼,封裝成模組,自用或者他用都可
3.# 第三方模組
別人寫的程式碼發到網上的,可直接下載使用的模組

(4)模組的四種表現形式

1.使用python程式碼編寫的py檔案  # 掌握
2.多個py檔案組成的資料夾(包)  # 掌握
3.已被編譯為共享庫或DLL的c或C++擴充套件(瞭解)
4.使用C編寫並連結到python直譯器的內建模組(瞭解)

2、模組的兩種匯入方式

方式一:import md

import md  # md是py檔名
print(md.name)  # 呼叫md.py檔案下的name變數名

注意:

(1)當前檔案進行呼叫md,當前檔案是執行檔案,md是被匯入檔案

(2)內部原理:

執行當前檔案產生一個當前檔案的名稱空間

使用import句式匯入模組檔案

當前檔名稱空間產生一個模組的名字執行匯入檔案的名稱空間

通過該名字點的方式就可使用被匯入模組中的資料

(3)若重複匯入同一個檔案,效果是一樣的

(4)兩者檔案有同樣的名字,不衝突,優先呼叫本名稱空間的變數名

方式二:from md import name

import後面可以跟多個變數名或者函式名等,呼叫多個進行使用

from md import name,money,read1  # 呼叫多個也可以,不寫的不能使用
print(name)  # jasonNB
name = 'kevin'
print(name)  # kevin  name在當前檔案有則使用當前檔案

3、匯入補充

(1)可以給模組取別名

目的是為了有時候import後面的模組名或變數名較複雜的時候取個簡單的別名

import md as m
print(m.name)  # 點方式呼叫

from md import name as n
print(n)  # 直接使用,注意避免與當前檔案下變數名衝突

(2)連續匯入多個模組或者名字

import time, sys, md
from md import name, read1, read2
注意:在匯入多個模組或者名字的時候,最後好有相似功能的部分一起匯入,否則最好按照下面分開匯入:
import time
import sys
import md

(3)通用匯入

使用*代替模組中所有的名字

from md import *  # 星號表示md.py中所有的名字
同時,另一方面在模組檔案用可以使用__all__限制可以使用的名字,這時候星號就會失效,依據__all__後面列舉的名字
__all__ = [name, age]

作業

1.利用比較好看的畫圖軟體詮釋出
	兩種模組匯入方式的內部內部  圖文相結合
2.整理今日內容部落格、錄音、單詞
3.嘗試將之前的週末大作業的多個函式拆分到不同檔案中以模組匯入的形式呼叫執行

1.兩種模組匯入方式內部原理圖