leetcode2097 合法重新排列數對
阿新 • • 發佈:2022-03-20
迭代器
常見內建函式(二)
# help() 檢視註釋資訊 # help(len) 檢視len函式的註釋資訊 # id() 返回相當於目標記憶體地址的一串數字 # print(id('name')) # >>>18096640 相當於name字串的記憶體地址 # int() 型別轉換,進位制轉換,其他型別轉成整形,其他進位制轉換成十進位制 # res = '123' # b = 0b101010 # print(int(res),type(res)) 字串必須是純數字,否則報錯 # print(int(b)) # >>>123 <class 'str'> # >>>42 # isinstance() 判斷資料型別 # print(isinstance(12,str)) # print(isinstance(12,int)) # >>>False # 結果不是預期型別返回FALSE # >>>True # 結果是預期型別返回True # pow() 冪指數 # print(pow(2,3)) # 第一個引數為底數,第二個引數為指數 # >>>8 # round() 四捨五入 # print(round(11.6778,2)) # 第二個引數可以指定保留幾位小數,不寫預設一位小數 # print(round(11.5)) # >>>11.68 # >>>12 # sum() 求和 # print(sum([1,2,3,4,5,6,7,8,9])) # >>>45
可迭代物件
# 1. 什麼叫迭代? 迭代就是更新換代,每一次迭代的過程都要依賴於上一次的結果 ''' n = 1 while True: print(n) # 上述只是單純的迴圈,沒有結果的變化,不屬於迭代 while True: n += 1 print(n) # 上述程式碼就屬於迭代,因為結果每次都是根據上一次的在變化 l1 = [11, 22, 33, 44, 55] # 迭代取值 i = 0 while i < len(l1): print(l1[i]) i += 1 ''' # 2. 什麼是可迭代物件? 可以點出__iter__方法的都可以稱為可迭代物件 '''__iter__讀作雙下iter''' # 3. 哪些資料型別是可迭代物件? i = 11 # 整型不是 f = 11.11 # 浮點型不是 s = 'jason' # 字元是 l = [1,2,3,4] # 列表是 d = {'name':'jason','age':18} # 字典是 t = (1,2,3,4) # 元組是 se = {1,2,3,4,5} # 集合是 b = True # 布林值不是 f = open() # 檔案是 def index():pass # 普通函式不是 ''' 屬於可迭代物件的有 字串、列表、字典、元組、集合、檔案物件 可迭代物件其實就是為了後續迭代取值做準備 提供了不依賴於索引取值的方式 可迭代物件都可以進行for迴圈! '''
迭代器物件
# 1. 什麼是迭代器物件? 可迭代物件呼叫__iter__方法後生成的就是迭代器物件 # 2. 迭代器物件有什麼特徵? 可以點出__iter__和__next__方法 # 3. 如何理解迭代器物件 迭代器物件能夠極大的節省儲存空間,類似於工廠,只有你需要使用資料的時候他才給你資料,不需要使用他就是一個工廠殼子,只佔工廠面積的空間 # 4. 迭代器物件如何取值? 呼叫__next__方法即可,呼叫一次給你一個值,取完了再取會直接報錯!!! ps:開闢了一種不需要索引取值的方式(for迴圈底層依據的就是迭代器物件) '''有了迭代器物件才出現了針對字典和集合的迭代取值操作''' # 5. 迭代器物件補充說明 # 1. 雙下方法簡寫(不是所有雙下方法都可以) ''' __方法名__ 等價於 方法名() __iter__ iter() __next__ next() ''' eg: print(len([1,2,3,4,5,6])) print([1,2,3,4,5,6].__len__()) 執行結果: 6 6 # 2. 有些可迭代物件本身也是迭代器物件>>>:檔案物件 # 3. 可迭代物件呼叫一次__iter__方法變成迭代器物件,繼續呼叫結果還是迭代器物件,所以,檔案本身既是可迭代物件又是迭代器物件,因為無論執行多少次__iter__,檔案物件都還是迭代器物件 eg: res = 'petter' res1 = 'oscar' print(res.__iter__()) print(res1.__iter__().__iter__().__iter__()) 執行結果: <str_iterator object at 0x020D8B30> <str_iterator object at 0x020D8BF0> # 無論執行多少次__iter__,結果都是iterator物件 # 4. 迭代取值的要求 '''迭代器物件每執行一次__next__,去除一個值''' eg: res = 'petter' print(res.__iter__().__next__()) print(res.__iter__().__next__()) print(res.__iter__().__next__()) s = res.__iter__() print(s.__iter__().__next__()) print(s.__iter__().__next__()) print(s.__iter__().__next__()) 執行結果: p p p p e t # 為什麼前三次取值結果都是p,而後面三次是p e t? ''' 前三次取值,每次取值之前都把res執行了一遍__iter__,相當於每次取值前都把res初始化成一個新的迭代器物件,所以只能取出p,而後面s是res轉換成的迭代器物件,迭代器物件再呼叫__iter__,結果還是他本身,哪怕你已經取過值了,結果還是本身,再取值也是接著後面取 '''
for迴圈的內部原理
# for迴圈內部就是一個迭代器
# 用迭代器輸出列表
eg:
l1 = [1,2,3,4,5,6,7,8,9]
res = l1.__iter__()
i = 0
while i < len(l1):
print(res.__next__())
i += 1
執行結果:
1
2
3
4
5
6
7
8
9
# 通過結果可以看到,這段程式碼實現的功能和for迴圈陣列l1的結果一毛一樣,所以可以看出,for迴圈的本質就是通過迭代器挨個取值。這也是為什麼可迭代物件都可以進行for迴圈
"""
for迴圈底層原理
for 變數名 in 可迭代物件:
迴圈體程式碼
1.會將in後面的資料呼叫__iter__()變成迭代器物件
為什麼檔案物件也可以for迴圈 因為本身就是迭代器物件 再次呼叫不變
2.針對產生的迭代器物件依次呼叫__next__()方法迭代取值
3.當值取完之後 會自動處理報錯並退出迴圈
"""
異常處理
# 1. 什麼是異常?
程式碼執行出錯之後就是異常 異常會導致程式立刻停止
是我們以後在程式設計過程中需要極力避免的情況(異常的外號>>>:bug)
# 2. 異常資訊的組成部分
Traceback (most recent call last):
File "/Users/jiboyuan/PycharmProjects/day16/05 異常處理.py", line 3, in <module>
name
NameError: name 'name' is not defined
1.line關鍵字所在的一行
用於提示你程式碼哪一行出錯了 點選地址可以直接跳到出錯的那一行
'''如果報錯的資訊很長 一般最後一個才是'''
2.NameError錯誤的型別
程式碼的報錯也可以分為很多型別,錯誤型別會以Error結尾
3.name 'name' is not defined
具體的報錯原因(就是解決報錯的答案),可以把這一行放到百度搜,有奇效,具體報錯內容跟在錯誤型別後面,還是找Error就可以了
# 3. 異常的分類
1. 語法異常
不被允許的,如果出錯了必須立刻改正,程式碼執行不起來,必須改正後才可以跑起來
2. 邏輯異常
可以允許,如果出錯了儘快修改,程式碼可以執行,但是得不到想要的結果
# 4. 異常的型別
# 異常的型別有很多,可以根據名字判斷異常種類,如
NameError 名稱錯誤
IndexError 索引錯誤
KeyError 鍵錯誤
# 異常型別都是由種類+Error組成,找到這個單詞,照著名字翻譯就可以
異常處理實操
'''有時候針對可能會出錯的程式碼 也可以自己提前寫好處理措施'''
正常情況下程式碼出錯 肯定是直接導致程式停止
但是也可以自己通過程式碼來處理 從而避免程式的停止
# 基本語法結構
try:
可能出錯的程式碼
except 錯誤型別1 as e: # e指代錯誤資訊,此處語法類似於open
處理措施
except 錯誤型別2 as e:
處理措施
...
# 萬能異常處理
try:
可能出錯的程式碼
except Exception as e: # 當我們不知道會出什麼型別的錯時,就用這個也可以
處理措施
##############################################
異常處理使用準則
1.被檢測的程式碼越少越好
2.能儘量少用就儘量少用
##############################################
異常處理了解
# 1. 和else連用
作用:當try監測的程式碼沒有發生異常,正常執行過後執行else子程式碼
語法:
try:
可能出錯的程式碼
except Exception as e:
處理措施
else:
沒有出錯執行的程式碼
# 2. 和finally連用
作用:無論try監測的程式碼有沒有發生異常,執行完程式碼後都會執行finally子程式碼
語法:
try:
可能出錯的程式碼
except Exception as e:
處理措施
finally:
異常處理後執行的程式碼
# 3. 全部整合到一起使用
try:
name
except Exception as e:
print(e)
else:
print('沒報錯 好極了')
finally:
print('管你錯不錯 都執行')
# 4.斷言(瞭解中的瞭解)
作用:針對一個可能成立的結論進行預測,成功則沒啥事,失敗報錯!!!
語法: assert 被斷言內容
num = 1
assert isinstance(num,int) # num是int型別,程式正常執行
assert 1 > 2 # 1 < 2,程式報錯
# 5.主動報錯(需要掌握)
raise NameError('不爽 就要作!!!')
'''由於是主動報錯 所以可以非常明確的知道錯誤的型別'''
用異常處理和迭代器實現自定義for迴圈
# 上面我們寫了自定義for迴圈,當時我們自己定義了while迴圈結束條件,其實還可以用異常處理結束迴圈
eg:
l1 = [1,2,3,4,5,6,7,8,9]
# 迭代取值
res = l1.__iter__()
try:
while True:
print(res.__next__())
except Exception as e:
print(e)
執行結果:
1
2
3
4
5
6
7
8
9
# 這樣寫省去了計數的部分,更節省空間
# for迴圈本質:
進行了異常處理的迭代器
迭代取值與索引取值的對比
1. 索引取值
優勢:可以重複取值,取值沒有固定方向
劣勢:只能致辭有序的容器型別,無序的無法取值相容新沒有迭代取值高,且需要一個儲存索引的記憶體空間,需要的空間資源更大
2. 迭代取值
優勢:相容所有的容器型別,不需要額外空間儲存索引
劣勢:只能從左往右取值,並且無法重複取值
# 真正底層的迭代取值後續可能很少用 一般都是for迴圈代替
"""
迭代器裡面的東西是固定的 沒取一個就會少一個 取完就空了
"""