python迭代器-迭代器取值-for循环-生成器-yield-生成器表达式-常用内置方法-面向过程编程-05...
迭代器
迭代器
迭代:?# 更新換代(其實也是重復)的過程,每一次的迭代都必須基于上一次的結果(上一次與這一次之間必須是有關系的)?
迭代器:?# 迭代取值的工具?
為什么用迭代器:?# 迭代器提供了一種可以不依賴索引取值的方式?
# 會一直打印0,記得停止 # n = 0 # while True: # print(n)# 重復 + 每次迭代都是基于上一次的結果而來的 l = [1, 2, 3, 4, 5] s = 'hello' n = 0 while n < len(s):print(s[n])n += 1 # h # e # l # l # o 迭代小案例可迭代對象
''' 可迭代對象只要內置有 __iter__ 方法的都叫做可迭代對象(讀:雙下iter)補充: 針對雙下劃線開頭結尾的方法,推薦讀“雙下 + 方法名”基本數據類型中,是可迭代對象的有(str, list, tuple, dict, set), 文件對象(執行 __iter__ 之后還是本身,__next__之后還是他本身)可迭代對象執行內置的 __iter__ 方法,得到的就是該對象的迭代器對象 ''' n = 1 f = 1.1 s = 'hello' l = [1,2,34,] t = (1,2,34) s1 = {1,2,3,4} d = {'name':'jason'} f1 = open('xxx.txt','w',encoding='utf-8')# # res = s.__iter__() # res = iter(s) # # print(s.__len__()) # 簡化成了len(s) # res1 = l.__iter__() # res1 = iter(l) # res2 = f1.__iter__() # res2 = iter(f1) # print(res,res1,res2) # print(f1)# 可迭代對象執行內置的__iter__方法得到就是該對象的迭代器對象 實驗迭代器對象與可迭代對象的區別
''' 迭代器對象和可迭代對象有什么共同點迭代器對象1.內置有雙下iter( __iter__) 方法2.內置有 __next__ 方法ps:迭代器對象一定是可迭代對象,而可迭代對象不一定是迭代器對象 '''__iter__轉換迭代器對象
l = [1, 2, 3, 4] # 生成一個迭代器對象 iter_l = l.__iter__()# 迭代器取值 調用__next__ print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) # 1 # 2 # 3 # 4 # print(iter_l.__next__()) # 取完了 直接報錯 d = {'name':'jason','password':'123','hobby':'泡m'} # 將可迭代對象d轉換成迭代器對象 iter_d = d.__iter__() # 迭代器對象的取值 必須用__next__ print(iter_d.__next__()) print(iter_d.__next__()) print(iter_d.__next__()) # name # password # hobby # print(iter_d.__next__()) # 取完了 報錯StopIteration f1 = open('test1.txt', 'r', encoding='utf-8') # 調用f1內置的__iter__方法 iter_f = f1.__iter__() print(iter_f is f1) # True """ 迭代器對象無論執行多少次__iter__方法得到的還是迭代器對象本身(******) """ print(f1 is f1.__iter__().__iter__().__iter__().__iter__()) # True 列表-字典-文件對象舉例?# 迭代器對象無論執行多少次__iter__方法得到的還是迭代器對象本身(******)?
疑問:?# __iter__方法就是用來幫我們生成迭代器對象,而文件對象本身就是迭代器對象,為什么還內置有__iter__方法??? ---見for循環原理?
異常處理
d = {'name': 'jason', 'password': '123', 'hobby': '泡m'} iter_d = d.__iter__() # 異常處理 while True:try:print(iter_d.__next__())except StopIteration:print('老母豬生不動了')break # name # password # hobby # 老母豬生不動了 異常處理迭代器與迭代器對象總結
''' 可迭代對象:內置有 __iter__ 方法 迭代器對象:既內置有__iter__ 方法,也內置有__next__方法迭代取值的優點與缺點:優點:不依賴于索引取值內存中永遠只占一份空間,不會導致內存溢出缺點:不能獲取指定的元素取完之后會報StopIteration錯.. '''for循環內部原理
''' for 循環內部的本質1.將in后面的對象調用 __iter__ 轉換成迭代器對象 --> 所以前面的疑問,文件對象本來就是迭代器對象還有 __iter__ 方法2.調用__next__ 迭代取值3.內部有異常捕獲,StopIteration,當__next__報這個錯,自動結束循環 '''?內部原理同上面異常處理里的案例
生成器
生成器:?# 用戶自定義的迭代器,本質就是迭代器?
注意點:?# 函數內如果有yield關鍵字,那么加括號執行函數的時候并不會觸發函數體代碼的運行?,?# yield后面跟的值就是調用迭代器__next__方法你能得到的值?,?# yield既可以返回一個值也可以返回多個值 并且多個值也是按照元組的形式返回?
?yield 返回值(體現上面的注意點)
def func():print('first')yield # 函數內如果有yield 關鍵字,那么加括號執行函數的時候并不會觸發函數體代碼的運行 ***print('second')yield 2 # yield 后面跟的值就是調用迭代器 __next__ 方法你能得到的值print('third')yield 3, 4, 5 # 既可以返回一個值,也可以返回多個值,并且多個值也是按照元組的形式返回 g = func() # 生成器初始化:將函數變成迭代器 # g.__iter__() print(g.__next__()) # first # Noneprint(g.__next__()) # second # 2print(g.__next__()) # third # (3, 4, 5) 利用yield返回值小案例
# 自定義range 功能 for i in range(10):print(i, end='- ') print()def my_range(start, end, step=1): # 只傳一個參數的,range,判斷參數個數 搜:python只傳一個參數的rangewhile start < end:yield startstart += stepfor i in my_range(1, 10, 3):print(i) # 1 # 4 # 7 自定義實現rangeyield表達式形式傳入參數
# yield 表達式形式(傳參的第三種方式,直接傳參,閉包) def dog(name):print("%s 準備開始吃" %name)while True:food = yieldprint("%s 吃了 %s" %(name, food))print(dog) # <function dog at 0x000001C22A10BA60># 當函數內有yield 關鍵字的時候 調用該函數 不會執行函數體代碼 # 而是將函數變成生成器 g = dog("egon") # 把函數變成生成器,函數體沒有運行 g.__next__() # 不運行這個直接運行下面的會直接報錯 TypeError: can't send non-None value to a just-started generator # 必須將代碼運行至 yield 才能為其傳值 # egon 準備開始吃 g.send('狗不理包子') # 給yield 左邊的變量傳參,觸發了 __next__ 方法 # egon 吃了 狗不理包子 g.__next__() # egon 吃了 None g.send('餃子') # egon 吃了 餃子 利用yield傳入參數總結yield并與return作對比
''' 總結yield:1.yield 提供了一種自定義生成器的方式2.yield 會幫你將函數的運行狀態暫停住3.yield 可以返回值與return 之間的異同點:相同點:1.都可以返回值,并且都可以返回多個,返回多個都是包裝成元組不同點:1.yield 可以返回多次值,而return 只能返回一次函數立即結束2.yield還可以接收外部傳入的值''' 總結與對比常用內置方法
常見數學內置函數 abs 絕對值? ? ? pow 求平方? ? round? 四舍五入? ?divmod?將運算結果除數與余數存入元組
# abs 求絕對值 print(abs(-10.11)) # 10.11# pow 平方 print(pow(2, 4)) # 16# round 四舍五入 print(round(3.1656)) # 3# divmod 將運算結果除數與余數存入元組(可用于分頁器) print(divmod(100, 11)) # (9, 1) all_count = 101 counts_each_page = 5 total_pages, more = divmod(all_count, counts_each_page) if more:total_pages += more print(total_pages) # 21 --> 共101條內容,按每頁5條來分,需要分21頁 abs pow round divmod數據類型進制轉換? isinstance(判斷數據類型)? all(傳過來容器類型必須全部都是True才返回True)? ?any(有一個是True就返回True)? ?bool(將傳進來參數變成布爾類型)? ?bin(十轉二) oct(十轉八)? hex(十轉十六)? ? int(把指定類型轉成十進制)
# isinstance 判斷數據類型,后面統一用該方法判斷對象是否屬于某一個數據類型 n = 1 print(type(n)) print(isinstance(n, list)) # 判斷對象是否屬于某個數據類型 # <class 'int'> # False# all 傳過來的容器類型里必須全部是True,否則返回False # any 只要一個True,就返回True l = [0, 1, 2] print(all(l)) # 只要有一個是False,就返回False print(any(l)) # False # True# bool print(bool(1)) print(bool(0)) # True # False# bin oct hex 將十進制轉換成對應的進制 print(bin(10)) print(oct(10)) print(hex(10)) # 0b1010 二進制 # 0o12 八進制 # 0xa 十六進制# int 可以把指定進制轉成十進制 print(int('0b1010', 2)) # 10 isinstance all any bool bin oct hex int字符編碼? ascii (個人覺得沒啥用)? chr(將數字轉換成ascii碼 對應的字符)? ? ord (將字符按照ascii碼 轉成數字)? bytes(轉成二進制)
# ascii 個人覺得沒啥用 print(ascii('a')) # 'a' print(ascii(65)) # 65 print(ascii('c')) # 'c'# chr ord 將數字轉換成ascii 碼表對應的字符 將字符按照ascii 碼表轉成對應的數字 print(chr(65)) # A print(ord('A')) # 65# bytes 轉換成二進制 # s = b'hello' # print(s) # # b'hello' s = 'hello' print(s.encode('utf-8')) print(bytes(s, encoding='utf-8')) # b'hello' # b'hello' ascii chr ord bytes可迭代對象常見內置函數? slice? 切片(生成的是老母豬,節省空間)? enumerate? 給可迭代對象生成索引(假索引)
# slice 切片 myslice = slice(5) # 設置截取5個元素的切片 arr = range(10) print(arr) print(arr[myslice]) # 截取5個元素 print(arr) # range(0, 10) # range(0, 5) # range(0, 10)# enumerate 枚舉 可以指定起始位 l = ['a', 'b', 'c'] for i, j in enumerate(l, 1):print(i, j) # 1 a # 2 b # 3 c slice enumerate執行字符串中的python語句以及python字符串格式化? eval (執行字符串中的python語句,不夠強大)? ?exec (執行python中的語句,能執行邏輯的)? ?format(格式化字符串)
# eval exec 執行字符串里的代碼,eval 不支持邏輯代碼,只支持一些簡單的python代碼, exec可以執行邏輯代碼 s = """ print('hello baby~') # x = 1 # y = 2 # print(x + y) """# eval(s) # hello baby~ exec(s) # hello baby~# format 三種玩法 # ------ {} 占位 -------- print('{} like {}'.format('tank', 'jason')) # tank like jason # ------ {index} 索引 -------- print('{0} like {2}'.format('tank', 'egon', 'jason')) # tank like jason # ------ {name} 指名道姓(關鍵字) -------- print('{name} is {age} years old.'.format(age=18, name='jason')) # jason is 18 years old. eval exec format對象命名空間 callable(對象是否可調用)? dir (獲取該對象名稱空間里的名字)? globals (查看全局名稱空間的名字)? ? locals (返回當前位置名稱空間的名字)? help (查看函數的注釋)
# callable 可調用的,可以加括號執行相應功能 def index():pass l = [1, 2, 3, 4, 5] print(callable(index)) print(callable(l)) # True # False# dir 獲取當前對象名稱空間里面的名字(所有他能夠支持的名字),可以是任何對象 l = [1, 2, 3] print(dir(l)) # ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] # import test # print(dir(test)) # print(test.name)# globals 無論在哪,查看的都是全局名稱空間 # locals 當前語句在那個位置,就會返回哪個位置所存儲的所有名字 def index():'''index的注釋:return: 沒有返回值'''username = "局部名稱空間里的username"print(locals()) # 當前語句在那個位置,就會返回哪個位置所存儲的所有名字print(globals()) # 不受位置影響 # {'__name__': '__main__'-------省略一大堆------- 'l': ['a', 'b'], 'i': 2, 'j': 'b'.....>} index() # {'username': '局部名稱空間里的username'}# help 查看函數注釋 print(help(index)) # Help on function index in module __main__: # # index() # index的注釋 # :return: 沒有返回值 # # None callable dir globals locals help面向過程編程
概述:?# 面向過程就類似于流水線設置,將復雜問題分步實現?
優點:?# 可以將復雜的問題流程化,從而簡單化?
缺點:?# 可擴展性差,如有改動,可能會涉及超大面積更改?
小案例(牽一發動全身)
# 獲取用戶登錄 def get_info():while True:username = input(">>>:").strip()if not username.isalpha(): # 判斷字符串不能包含數字print('不能包含數字')continuepassword = input('>>>:').strip()confirm_password = input("confirm>>>:").strip()if password == confirm_password:operate_data(username,password)breakelse:print('兩次密碼不一致')# 2.處理用戶信息 def operate_data(username,password):# jason|123res = '%s|%s\n'%(username,password)save_data(res,'userinfo.txt')# 3.存儲到文件中 def save_data(res,file_name):with open(file_name,'a',encoding='utf-8') as f:f.write(res)def register():get_info()register() 正常版注冊 # 在用戶注冊時候讓用戶選擇用戶類型 # 1.獲取用戶輸入 def get_info():while True:username = input(">>>:").strip()if not username.isalpha(): # 判斷字符串不能包含數字print('不能包含數字')continuepassword = input('>>>:').strip()confirm_password = input("confirm>>>:").strip()if password == confirm_password:# 改動 ---------------------------------------------d = {'1':'user','2':'admin'}while True:print("""1 普通用戶2 管理員""")choice = input('please choice user type to register>>>:').strip()if choice not in d:continueuser_type = d.get(choice)# 函數的參數個數也要改變 operate_data(username,password,user_type)break# 改動 ----------------------------------------------else:print('兩次密碼不一致')# 2.處理用戶信息 # 函數定義時的的參數個數也要改變 ------------------------------------------ def operate_data(username,password,user_type):# jason|123# 拼接也要改動 ------------------------------------------res = '%s|%s|%s\n'%(username,password,user_type)save_data(res,'userinfo.txt')# 3.存儲到文件中 def save_data(res,file_name):with open(file_name,'a',encoding='utf-8') as f:f.write(res)def register():get_info()register() 擴展讓用戶可選擇用戶類型?擴展練習題(面試題)
1.請判斷下面代碼中的 res 是什么
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) res = list(g)# 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. res = [20, 21, 22, 23] 答案2.請判斷下面程序會輸出什么
# 已經提前把里面的東西取出來了 解析3.利用生成器表達式讀取文件行數
''' 需求: 讀取一個文件并返回每行數據的長度 ''' with open('test1.txt', 'w', encoding='utf-8') as f:for line in range(1000):f.write(f'www{line}aaa' * (line + 1) + '\n') # 列表推導式: 處理數據量大的文件會導致內存溢出. res = [len(line) for line in open('test1.txt', 'r', encoding='utf-8')] # print(res)# 生成器表達式: 處理數據量大的文件推薦使用. res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8')) print(res2) # <generator object <genexpr> at 0x000002B3748FD0A0> print(next(res2)) print(next(res2)) 解決方案4.寫出下面代碼的執行結果
# 請寫出下面代碼的執行結果 def mutipliers():return [lambda x: i*x for i in range(4)]print([m(2) for m in mutipliers()]) # [6,6,6,6] ---> 題目的正確答案 def multipliers():return [lambda x, i=i: i*x for i in range(4)]# 0, 1, 2, 3# [func(x): return 0*x, func(x): return 1*x,# func(x): return 2*x, func(x): return 3*x, ]print([m(2) for m in multipliers()]) # [0, 2, 4, 6]# [func(x): return 0*2, func(x): return 1*2, # func(x): return 2*2, func(x): return 3*2, ] # [0, 2, 4, 6] # [6, 6, 6, 6]# 閉包函數的延遲綁定 # 在內層函數執行時才會綁定變量i def multipliers2():list1 = []for i in range(4):def func(x, i=i):return x * ilist1.append(func)return list1print([m(2) for m in multipliers2()]) # [0, 2, 4, 6]# [0, 2, 4, 6] 思路(根據思路題目更改答案變更)?
轉載于:https://www.cnblogs.com/suwanbin/p/11189321.html
總結
以上是生活随笔為你收集整理的python迭代器-迭代器取值-for循环-生成器-yield-生成器表达式-常用内置方法-面向过程编程-05...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scrapy项目 - 数据简析 - 实现
- 下一篇: 怎么把本地的项目同时提交到两个仓库