day 13
迭代器:
作用:可以不依賴索引進行取值。
可迭代對象:
必須內置有__iter__方法
__iter__讀法:雙下+方法名
需要迭代取值的數據類型:
字符串、列表、元祖、字典、集合(均為可迭代對象)
文件對象:(迭代器對象)執行內置__iter__之后還是它本身。
f1 = open('xxx.txt','w',encoding='utf-8')
print(f1)
可迭代對象執行內置的__iter__方法之后就變成了迭代器對象。
迭代器對象:
1.有內置方法__iter__、__next__方法
l = [1,2,3,4]
__iter__l = l.__iter__()#生成迭代器對象
迭代器取值 需要調用__next__方法
print(__iter__l.__next__())
......
當取空時會直接報錯(StopIteration)
迭代器對象無論執行多少次__iter__()方法得到的還是迭代器本身。
f1=open('a.txt','r',encoding='utf-8')
print(f1? is? f1.__iter__().__iter__().__iter__().__iter__())
問:__iter__方法就是用來幫我們生成迭代器對象而文件對象本身就是迭代器對象,為什么還內置有__iter__方法???
因為如果沒有這個內置方法的話文件對象調用__iter__()時,就會報錯。
異常處理:
try:
.....
except StopIteration(錯誤類型):
“錯誤類型匹配時執行此處的代碼!”
迭代器的取值特點:只能依次的往后去,不能后退。
for循環的本質:
for? ...? ?in? ?...
關鍵字in的后面:可迭代對象。
for循環的內部本質:
1.將in后面的對象調用__iter__轉換成迭代器對象。
2.調用__next__迭代取值
3.內部有異常處理機制,用來捕獲錯誤類型StopIteration,當__next__出現這種錯誤類型時,自動調用break來結束本次循環。
迭代取值的優缺點:
優點:
1.不用依賴傳統的索引取值。
2.在內存中永遠只占一份空間,需要的時候再取出,不會導致內存溢出。
缺點:
1.不能夠只取出指定元素,只能依次取出。
2.當迭代器中的值被取完時會報錯。(StopIteration)
生成器:即用戶通過自定義的迭代器。
一般形式:
def? ? func():
? ? ? ?print('first')
? ? ? ? yield? ? 666? ? ? ?#函數體內有yield關鍵字時,加括號并不會取執行函數
? ? ? ? #yield? ? 1,2,3,4
#yield后面的值就是當你調用迭代器__next__方法時,你可以得到的值。
同時yield可以返回多個值,并且多個值也是按照元祖的形式返回的
g = func()? ? ? #生成器初始化:將函數變成迭代器
print(g.__next__())
自己手寫一個range(1,10,2)函數
def my_range(n,k,j):
while n<k:
yield n
n+=j
res = my_range(1,10,2)
print(res)
print(res.__next__())
yield表達式形式(了解內容)
def dog(name):
print('%s 準備開吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
# def index():
# pass
yield支持外界為其傳參(send())
當函數體內有yield關鍵字的時候,調用該函數不會執行函數體代碼,而是將函數變成一個生成器。
通過send()方法為yield傳值的時候,必須將代碼運行到yield才能夠為其傳值(運行至yield是會自動停止運行),通過send傳值是也會自動觸發__next__方法,進行輸出一次。
與return的異同點:
相同點:都可以返回多個值。
不同點:yield可以返回多次值,而return一次函數就結束了;yield還可以接受外部傳入的值。
生成器表達式:
# res = (i for i in range(1,10) if i != 4) # 生成器表達式
# print(res)
# """
# 生成器不會主動執行任何一行代碼
# 必須通過__next__觸發代碼的運行
生成器表達式的應用:
# with open('xxx.txt','r',encoding='utf-8') as f:
#(傳統的for循環方法)
# # n = 0
# # for line in f:
# # n += len(line)
# # print(n)
#(利用生成器表達式方法)
g = (len(line) for line in f)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
?print(sum(g))
面試題:
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 test())
# 第二次for循環g=(add(n,i) for i in (add(n,i) for i in test()))
print(n)
res=list(g)
"""
for i in (add(10,i) for i in test()): 會執行所有的生成器內部的代碼
add(n,i)
"""
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23] 答案
#D. res=[21,22,23,24]
常用的內置方法:
abs():求絕對值
print(abs(-11))#11
l = [1,2,3]
all(l)#只要有一個元素返回值為false,就返回false
any(l)#只要有一個元素返回值為True就返回true
globals():#查看全局名稱空間的變量名
二進制:bin()
八進制:oct()
十六進制:hex()
chr(97)#將數字轉換成ASCII碼表對應的字符。
order(‘a’)#將字符按照ASCII表轉換成對應的數字。
"""
面向對象需要學習的方法
classmethod
delattr
getattr
hasattr
issubclass
property
repr
setattr
super
staticmethod
"""
dir()#獲取當前對象的名稱空間里面的名字
l=[1,2,3]
print(dir(l))
divmod()#分頁器
print(divmod(101,10))#(10, 1)
enumerate #枚舉
l = ['a','b','c']
for i,j in enumerate(l):
print(i,j)
#結果:
0 a
1 b
2 c
eval(s):(提取字符串中的Python代碼并進行運算)不支持代碼邏輯只支持一些簡單的Python代碼
s='
print(1+2)
for i in range(10):
? ? ? ? print(i)
'
eveal(s1)#(報錯)
exec(s1)#(可以運行)
exec(s):(提取字符串中的Python代碼并進行運算)支持代碼邏輯,比eveal高級
# isinstance 后面統一改方法判斷對象是否屬于某個數據類型
# n = 1
# print(type(n))
# print(isinstance(n,list)) # 判斷對象是否屬于某個數據類型
round():#四舍五入
面向過程編程:
好處:
將復雜的問題流程化 從而簡單化
壞處:
可擴展性較差 一旦需要修改 整體都會受到影響
?
轉載于:https://www.cnblogs.com/yangjiaoshou/p/11190269.html
總結
- 上一篇: a=(1,)b=(1),c=(“1”)
- 下一篇: 由于代码已经过优化或者本机框架位于调用堆