使用
while
迴圈+例外處理+迭代器物件 完成for
迴圈迭代取值的功能
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
die_qi = l1.__iter__()
while True:
try:
res = die_qi.__next__()
print(res)
except Exception as e:
print('資料取完了')
break
生成器物件的本質
生成器物件其實本質上就是迭代器物件,內建有雙下戶線
iter
和雙下劃線next
方法
區別
迭代器物件就是
python
直譯器提供的各種資料型別或是檔案物件,但是生成器物件是程式設計師編寫的程式碼或是函數之類的關鍵字
生成器的兩種形式
使用def定義函數然後內部使用yield關鍵字
在使用函數+yield
關鍵字定義生成器的時候需要注意當我們使用括號呼叫函數的時候並沒有執行這個函數,而是把這個函數體程式碼變成了一個生成器物件,之後我們想要呼叫函數產生資料就需要跟迭代器一樣使用雙下劃線的next
方法,並且每次執行的時候如果遇到yield
關鍵字就會停止到那個位置,如果下方程式碼還有yield
關鍵字,下一次執行雙下劃線的next
方法就會執行到下一個yield
關鍵字處停止
def my_iter():
print('哈哈哈 椰子汁很好喝')
yield
'''1.函數體程式碼中如果有yield關鍵字
那麼函數名加括號並不會執行函數體程式碼
會生成一個生成器物件(迭代器物件)
'''
res = my_iter()
print(res)
# <generator object my_iter at 0x00000204CEDEBBA0>
'''2.使用加括號之後的結果呼叫__next__才會執行函數體程式碼'''
res.__next__()
# 哈哈哈 椰子汁很好喝
下面是多個yield的使用場景:
'''3.每次執行完__next__程式碼都會停在yield位置 下次基於該位置繼續往下找第二個yield'''
def my_iter():
print('哈哈哈 椰子汁很好喝')
yield 111, 222, 333
print('呵呵呵 從小喝到大')
yield 111, 222, 333
print('嘿嘿嘿 特種兵牌還可以')
yield 111, 222, 333
print('哼哼哼 千萬別整多了 倒沫子 頭髮掉光光')
yield 111, 222, 333
res = my_iter()
r1 = res.__next__()
print(r1)
r2 = res.__next__()
print(r2)
r3 = res.__next__()
print(r3)
r4 = res.__next__()
print(r4)
'''4.yield還有點類似於return 可以返回返回值'''
'''結果如下:
哈哈哈 椰子汁很好喝
(111, 222, 333)
呵呵呵 從小喝到大
(111, 222, 333)
嘿嘿嘿 特種兵牌還可以
(111, 222, 333)
哼哼哼 千萬別整多了 倒沫子 頭髮掉光光
(111, 222, 333)
'''
注意:在上面的程式碼執行過程中我們也發現了yield關鍵字跟return一樣可以返回返回值
def my_range(start_num, end_num=None, step=1):
# 判斷end_num是否有值 沒有值說明使用者只給了一個值 起始數位應該是0 終止位置應該是傳的值
is_back = False
if not end_num:
# 判斷第二個結束為止是否有引數,如果沒有就把傳給起始位置的引數給結束為止,其實位置變成0
end_num = start_num
start_num = 0
if step == 0:
yield '位移量不能為0'
if step < 0:
# 判斷取值的步頻是否為反方向
# 如果是反方向的步頻,判斷起始位置和結束為止是否前面的大後面的小
if not start_num > end_num:
yield '引數大小錯誤'
else:
is_back = True
# 起始位置和結束為止是前面的大後面的小的時候就返回True
while start_num < end_num or is_back:
# 起始位置小於結束位置的時候或是步頻為負數的時候判斷正確的話就輸出資料值
if start_num < end_num:
# 起始位置小於結束位置
print(start_num)
yield start_num
start_num += step
elif is_back:
# 步頻為負數
if start_num > end_num:
yield start_num
start_num += step
else:
is_back = False
# 定義了模仿range方法的功能後,用for迴圈的方式呼叫內部資料值
for i in my_range(100, 50, 0):
print(i)
當我們使用
yield
關鍵字的時候可以用變數名系結yield
關鍵字,然後就可以使用send
方法傳參,然後會再次執行到yield
關鍵字處停止執行
def eat(name, food=None):
print(f'{name}準備用餐')
while True:
food = yield
print(f'{name}正在吃{food}')
res = eat('kevin')
res.__next__()
res.send('漢堡') # 1.將括號內的資料傳給yield前面的變數名 2.再自動呼叫__next__
res.send('包子')
res.send('麵條')
'''
kevin準備用餐
kevin正在吃漢堡
kevin正在吃包子
kevin正在吃麵條
'''
yield
1. 可以有返回值
2. 函數遇到yield不會結束,只會'停住'
3. yield關鍵字把函數變成了生成器,支援迭代取值了
return
1. 可以有返回值
2. 遇到return關鍵字直接結束函數執行
"""
面試題(有難度)
大致知道流程即可
"""
def add(n, i): # 普通函數 返回兩個數的和 求和函數
return n + i
def test(): # 生成器
for i in range(4):
yield i
g = test() # 啟用生成器
for n in [1, 10]:
g = (add(n, i) for i in g)
"""
第一次for迴圈
g = (add(n, i) for i in g)
第二次for迴圈
g = (add(10, i) for i in (add(10, i) for i in g))
"""
res = list(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]
'''不用深入研究 大致知道起始數即可'''"""
面試題(有難度)
大致知道流程即可
"""
def add(n, i):
return n + i
# 定義了一個add函數,作用求和
def test(): # 生成器
for i in range(4):
yield i
# 定義了一個生成器
g = test() # 啟用生成器
# 啟用了生成器,這樣就而已用for迴圈取值了
for n in [1, 10]:
g = (add(n, i) for i in g)
"""
第一次for迴圈
這裡就相當於給g重新系結了一個生成器沒有執行程式碼
g = (add(n, i) for i in g)
第二次for迴圈
這裡就相當於用到for迴圈去(add(n, i) for i in g)裡面取值了,這個時候的n是10,生成器給的四個值是0、1、2、3,然後執行add就等於c選項
g = (add(10, i) for i in (add(10, i) for i in g))
"""
res = list(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]
'''不用深入研究 大致知道起始數即可'''
# print(abs(10))
# print(abs(-10)) # 絕對值
# l = [1, 2, 3, 0]
# print(all(l)) # True
# print(any(l))
arr = range(10)
myslice = slice(5) # 設定擷取5個元素的切片
"""
100條資料 10條 10頁
99條 10 10頁
101條 101 11
"""
# page, more=divmod(100, 10)
# page, more=divmod(99, 10)
# page, more=divmod(2005, 10)
# if more:
# page += 1
# print(page)
# res="""print('hello world')""" #
res="""
# 這是註釋
for i in range(10):
print(i)
""" #
# eval(res) # 識別簡單的python程式碼
# exec(res)
# if type(123) is int:
# print('123')
# print(type('123') is int) # 判斷資料型別的
# print(isinstance('123', int))
# print(isinstance(123, int))
# print(isinstance('123', str))
# print(isinstance([1,2,3,4], list))
# print(isinstance({'a':1}, dict))
# print(chr(65))
# print(chr(97)) # 根據ASCII碼錶,填入對應的十進位制,返回對應的字元
# print(ord('A'))
# print(ord('z')) # 根據ASCII碼錶,填入對應的字元,返回對應的十進位制
# l = [10, 20, 30 ,40, 50]
# print(sum(l)) # 求和
# print(pow(4, 3)) # 4 ** 3
# print(pow(2, 3)) # 4 ** 3
s = '你好啊'
# res=s.encode('utf-8')
# print(res)
# ret = res.decode('utf-8')
# print(ret)
# res=bytes(s, 'utf-8')
# print(res)
# print(str(res, 'utf-8'))
def index():
print('from index')
# print(callable(index)) # 檢視是否能夠被呼叫
'''健壯性'''
# res=callable(index)
# if res:
# index()
# else:
# ''''''
# def func(name, age):
# print(locals()) # {'name': 1, 'age': 2}
# func(1, 2)
# 複數,而不是負數
# 1+2j
# 四捨五入
print(round(3.4))
print(round(3.5))
print(round(3.6))