函數 迭代器,生成器




# 一 迭代器

'''
什么是迭代器:
迭代:就是一個重復的過程,每次的迭代都必須基於上一次的結果
迭代器:就是可以迭代取值的工具

重點:迭代器不是簡單的重復,而是重復+每一次迭代都是基於上一次的結果而來的



特點:那我們為什么要用迭代器:
因為迭代器給我們提供了一種不依賴於索引取值的方式


1.什么是可迭代對象:只有內置有__iter__方法的都叫做可迭代對象


2.在基本的數據類型中,是可迭代對象的有:
str ,list,tuple,dict,set

3.但是如果在文件對象中(執行內置的__iter__之后還是本身,沒有任何變化):因為文件對象本身就是迭代器對象


重點:如果可迭代對象執行內置的__iter__方法得到的就是該對象的迭代器對象

案例:
res = s.__iter__() # res = iter(s)
print(s.__len__()) # 簡化成了len(s)
res1 = l.__iter__() # res1 = iter(l)
res2 = f1.__iter__() # res2 = iter(f1)



迭代器對象
1.內置有__iter__方法
2.內置有__next__方法(可以通過這個取值)
注意點:迭代器一定是可迭代對象
而可迭代對象不一定是迭代器對象


那么如何生成一個迭代器對象?
舉例:
l = [1,2,3,4]
可以用__iter__方法來生成一個迭代器對象:
iter_l = l.__iter__()#這樣就生成了一個迭代器對象

如果我們想要迭代器取值的話,就需要調用 __next__方法了

print(iter_l.__next__())
一次只會取一個值,還要取的話,要在調用__iter__方法
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())

注意:l 列表中只有4個值,但是我取了五次,已經沒有值了,
那么第五次就會報錯

如何來解決這個問題:我們可以用異常捕獲來解決
案例:
# 異常處理
while True:
try:
print(iter_l.__next__())
except StopIteration:
print('老母豬生不動了')
break

重點:
1.迭代器對象取值的時候必須,必須調用__iter__方法來取值,而且一次只能取一次,取幾次調用幾次
2.迭代器對象無論執行多少次__iter__方法得到的都是迭代器對象本身
f1 = open('xxx.txt','r',encoding='utf-8')
調用f1內置的__iter__方法
iter_f = f1.__iter__()
print(iter_f is f1)
print(f1 is f1.__iter__().__iter__().__iter__().__iter__())
3.迭代器取值的時候,只能往后依次取,不能后退



重點:__iter__方法就是用來幫我們生成迭代器對象的,
而文件對象本身就是迭代器對象,為什么內置還有__iter__方法

案例:
d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()
print(d.__iter__().__next__())
print(d.__iter__().__next__())
print(d.__iter__().__next__())
如果這樣寫的話,打印出來的結果都是 name
因為他每一次取值的時候,都重新初始化的這個迭代器對象


案例:
l = [1,2,3,4,5]
iter_l = l.__iter__()

print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
# print(iter_l.__next__())# 會報錯,值取完了

# 可以通過異常處理來解決
while True:
try:
print(iter_l.__next__()) # 可以捕獲錯誤
except StopIteration:
print('取完了')
break
'''



# 二 生成器

'''
生成器:就是用戶自定義的迭代器,其實本質上就是迭代器
注意點:
1.如果函數內有yield關鍵字,那么加括號執行函數的時候就不會觸發函數體的代碼運行
2.yield后面要是有返回值,就是可以通過調用__next__方法能得到的值
3.yield可以返回一個或者多個值,返回多個值是按照元組的方式返回

案例:
# def func():
# print('zy')
# yield 1111
# print('egon')
# yield 2222
# print('tank')
# yield 3333
# print('jason')
# yield # 如果下面調用的話 返回None
# yield # 如果下面調用的話 返回None
#
# # g = func()
# # print(g)# 運行的結果 <generator object func at 0x000001E25E3AEFC0>
# g = func()# 生成器初始化:將函數變成迭代器
# print(g)
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())



yield
1.幫你提供了一種自定義生成器方式
2.會幫你將函數的運行狀態暫停住
3.可以返回值

與return之間異同點
相同點:都可以返回值,並且都可以返回多個
不同點:
yield可以返回多次值,而return只能返回一次函數立即結束
yield還可以接受外部傳入的值


案例:自己寫一個簡單的range
def my_range(start,end,step=1):
while start < end:
yield start
start += step
for j in my_range(1,100,2):
print(j)


'''


# 三 for 循環的本質

'''
d = {'name':'jason','password':'123','hobby':'泡m'}
for i in d:
print(i)
for 循環后面的in 跟的是一個可迭代對象


for 循環內部的本質
1.將 in 后面的對象調用__iter__轉換成迭代器對象
2.調用__next__迭代取值
3.內部有異常捕獲StopIteration,當__next__報錯時,會自動結束循環

可迭代對象:內置有__iter__方法
迭代器對象:內置有__iter__方法 也有__next__方法

迭代取值:
優點:
1.不依賴於索引取值
2.內存中永遠都只占一份空間,不會導致內存溢出

缺點:
1.不能獲取指定的元素
2.值取完的時候會報StopIteration錯

案例:
l = [1,2,3,4]
res = map(lambda x:x+1,l)
print(map(lambda x:x+1,l))
print(res.__next__())
print(res.__next__())
print(res.__next__())
'''

# 四 生成器表達式
'''
生成器不會主動執行任何一行代碼,
必須通過__next__觸發代碼的運行

案例:生成器表達式
res = (i for i in range(1,1000) if i !=4)
print(res)

print(res.__next__())
print(res.__next__())
print(res.__next__())

'''
# 五 常用的一些內置函數
'''
print(abs(-11.11)) # 求絕對值


print(all(l)) # 只要有一個為False就返回False
print(any(l)) # 只要有一個位True就返回True

print(locals()) # 當前語句在哪個位置 就會返回哪個位置所存儲的所有的名字
print(globals()) # 無論在哪 查看的都是全局名稱空間


print(chr(97)) # 將數字轉換成ascii碼表對應的字符
print(ord('a')) # 將字符按照ascii表轉成對應的數字


callable 查看函數是否可調用


dir獲取當前對象名稱空間里面的名字


index 索引

enumerate 枚舉


format 三種玩法
{}占位
{index} 索引
{name} 指名道姓

isinstance 后面統一改方法判斷對象是否屬於某個數據類型

print(isinstance(n,list)) # 判斷對象是否屬於某個數據類型

print(pow(2,3))# 2的三次方


print(round(5.3))# 取整數,可以四舍五入
'''

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com