1. 程式人生 > 其它 >迭代器+生成器+函式遞迴+三元表示式+生成式+二分法

迭代器+生成器+函式遞迴+三元表示式+生成式+二分法

內容概要

  • 迭代器
  • 生成器
  • 函式遞迴
  • 三元表示式
  • 生成式
  • 二分法

內容詳細

  • 迭代器

    # 1.什麼是迭代器
    	# 迭代器指的是迭代取值的工具,迭代是一個重複的過程,
        # 每次重複都是基於上一次的結果而繼續的,單純的重複並不是迭代
        
    # 2.為何要有迭代器
    	# 迭代器是用來迭代取值的工具,而涉及到把多個值迴圈取出來的型別
        # 有:列表、字串、元組、集合、字典、檔案
        l = ['ycc','xixi','haha']
        count = 0
        while count < len(l):
            print(l[count])
            count += 1
            
            # 上述迭代取值的方式只適用於有索引的資料型別:列表、字串、元組
            # 為了解決基於索引迭代取值的侷限性,python必須提供一種能夠不依賴於索引的取值方式,這就是迭代器
            
    # 3.如何用迭代器
    	# 可迭代物件:但凡內建有__iter__方法的都稱為可迭代的物件
        # s1 = 'abc'
        # s1_iterator = s1.__iter__()
        # l = []
        # l_iterator = l.__iter__()
        # set1 = {1,2,3}
        # set1_iterator = set1.__iter__()
        # dic = {'a':1,'b':2,'c':3}
        # dic_iterator = dic.__iter__()
        # tup = (1,2,3)
        # tup_iterator = tup.__iter__()
        # with open('a.txt','w') as f:
        #	f.__iter__()
        #   pass
        
    # 4.例:
    	s1 = 'abc'
        s1_iterator = s1.__iter__()  # 等價於 iter(s1)
        print(s1_iterator.__next())  # a
        print(s1_iterator.__next())  # b
        print(s1_iterator.__next())  # c
        print(s1_iterator.__next())  # error:StopIteration
        # 只有三個值取完就報錯
        
    # 可迭代物件與迭代器物件詳解:
    	1.可迭代物件(可以轉換成迭代器的物件):內建有__iter__()方法的物件
        	可迭代物件.__iter__() = 迭代器物件
         2.迭代器物件:內建有__next__()並且內建有__iter__()
        	迭代器物件.__next__() = 得到的下一個值
            迭代器物件.__iter__() = 得到迭代器本身,說白了掉了跟沒調一個用
            
    # 1.
    # d = {'a':1,'b':2,'c':3}
    # d_iterator = d.__iter__()
    # print(d_iterator is d_iterator.__iter__())  # True  迭代器物件 = 迭代器物件.__iter__()
    
    # 2.
    # for迴圈的工作原理:for迴圈可稱之為迭代器迴圈
    	# 1. d.__iter__()得到一個迭代器物件
        # 2. 迭代器物件.__next__()得到一個返回值,然後將返回值賦給k
        # 3. 迴圈往復步驟2,直到丟擲異常for迴圈會捕捉異常結束
        
    	d = {'a':1,'b':2,'c':3}
        for k in d:
            print(d)
            
        d_iterator = d.__iter__()
        while True:
            try:
                print(next(d_iterator))
            except StopIteration:
                break
                
        print('=============================>')
        d_iterator = d.__iter__()  # 這裡必須再調一次迭代器功能,因為上面已經將值取完了
        while True:
            try:
                print(next(d_iterator))
            except StopIteration:
                break
                
    # 3.
    	print(list('hello'))  # ['h', 'e', 'l', 'l', 'o'] 原理同for迴圈
        
    # 4.
    # 可迭代物件:字串、列表、字典、元組、集合、檔案物件
    # 迭代器物件:檔案物件
    # 可迭代物件只有呼叫內建方法.__iter__()才能變成迭代器物件
    # 檔案物件既是可迭代物件也是迭代器物件
    # with open('user.txt','w') as f:
    #     f.__iter__()
    #     f.__next__()
    #     pass
    
    # 5.迭代器的優缺點總結
    # 優點:
    #     1.為序列和非序列型別提供了一種統一的迭代取值方式。
    #     2.惰性計算:迭代器物件表示的是一個數據流,可以只在需要時才去呼叫next來計算出一個值,
    #     就迭代器本身來說,同一時刻在記憶體中只有一個值,因而可以存放無限大的資料流,而對於其他容器型別,
    #     如列表,需要把所有的元素都存放於記憶體中,受記憶體大小的限制,可以存放的值的個數是有限的。
    # 缺點:
    #     1.除非取盡,否則無法獲取迭代器的長度
    #     2.只能取下一個值,不能回到開始,更像是‘一次性的’,迭代器產生後的唯一目標就是重複執行next方法直到值取盡,
    #       否則就會停留在某個位置,等待下一次呼叫next;若是要再次迭代同個物件,
    #       你只能重新呼叫iter方法去建立一個新的迭代器物件,如果有兩個或者多個迴圈使用同一個迭代器
    # ,    必然只會有一個迴圈能取到值
          
        
    
  • 生成器

    # 如何得到自定義的迭代器 
    # 在函式內一旦存在yield關鍵字,呼叫函式並不會執行函式體程式碼,會返回一個生成器物件,生成器即自定義的迭代器
    
     def func():
         print('第一次')
         yield 1
         print('第二次')
         yield 2
         print('第三次')
         yield 3
         print('第四次')
    
     func()
     g = func()
     g.__iter__()
    
    
    # # 會觸發函式體程式碼的執行,然後遇到yield停下來,將yield後的值當作本次呼叫的結果返回
     res1 = g.__next__()
     print(res1)
     res2 = g.__next__()
     print(res2)
     res3 = g.__next__()
     print(res3)
    # res4 = g.__next__()  # StopIteration
    
    # ps:補充
    # len('aaa')  # 等同於'aaa'.__len__()
    # next(g)  # 等同於g.__next__()
    # iter(可迭代物件)  # 等同於 可迭代物件.__iter__()
    
    # 應用:
    def my_range(start,stop,step=1):
        while start < stop:
            yield start
            start += step
    
    g = my_range(1,5,2)
    while True:
            try:
                print(next(g))
            except StopIteration:
                break
    
    # for i in my_range(1,10,2):
    #     print(i)
    
    
    
    # ps:retrun 與 yield的區別:
    #     有了yield關鍵字,我們就有了一種自定義迭代器的實現方式。yield可以用於返回值,
    #     但不同於return,函式一遇到return就結束了,而yield可以儲存函式的執行狀態掛起函式,用來返回多次值。
    
    
  • 函式遞迴

    # 函式遞迴呼叫:是函式巢狀呼叫的一種特殊形式
    # 具體是指:在呼叫函式的過程中,直接或間接的又呼叫到本身
    
    # import sys   瞭解
    # print(sys.getrecursionlimit())  # 1000  最多死迴圈1000次
    # sys.setrecursionlimit()  # 這個方法可以將限制1000次進行修改
    
    # 一、遞迴定義
        # 直接呼叫本身(死迴圈)
            def f1():
                print('是我自己')
                f1()
            f1()
    
        # 間接呼叫本身(死迴圈)
            def f1():
                print('===>f1')
                f2()
            def f2():
                print('===>f2')
                f1()
            f1()
            
        # 一段程式碼的迴圈執行的方案有兩種
        	# 方案一:while、for迴圈
            	while True:
                    print(11)
                    print(22)
            # 方案二: 遞迴的本質就是迴圈
            	def f1():
                    print(1)
                    print(2)
                    f1()
                f1()
                
    # 二、要強調的一點是:
    # 遞迴呼叫不應該無限的呼叫下去,應該在滿足某種條件下結束遞迴呼叫
    # 例:取小於10的數
    	# 方案一 :while、for迴圈
        	count = 0
            while count < 10:
                print(count)
                count += 1
                
        # 方案二: 遞迴
        	def func(count):
                if count > 9:
                    return
                count += 1
                func(count)
             func(0)
            
    # 三、遞迴的兩個階段
    # 回溯:一層一層呼叫下去
    # 遞推:滿足某種結束條件,結束遞迴呼叫,然後一層一層返回
    
    # 例:
    	# age(5) = age(4)+10
        # age(4) = age(3)+10
        # age(3) = age(2)+10
        # age(2) = age(1)+10
        # age = 18
        
        def age(n):
            if age == 18:
                return 
            return age(n) = age(n-1)+10
        age()
        
    # 四、遞迴函式的應用,打印出下面列表的所有元素
    l = [1,[2,[3,[4,5,[6,[7,[8,9,10]]]]]]]
    for x in l:
        # 如果是列表應該再迴圈再判斷
        if type(x) is list:
            pass # 這裡會套無數個判斷
        else:
            print(x)
    # 轉換思路用遞迴        
    def func(list1)
        for x in list1:
            if type(x) is list:
    			func(x)
            else:
                print(x)
    func(l)
        
    
    
  • 三元表示式

    def func(x,y):
        if x > y:
            return x
        else:
            return y
    func()
    
    # 三元表示式 簡化函式體
    # 格式:條件成立時要返回的值 if 條件 else 條件不成立時要返回的值
    def func(x,y)
    	return x if x > y else y
    res = func(1,3)
    print(res) # 3
    
  • 生成式

    # 1.列表生成式
    	l = ['alex_dsb','egon_dsb','lxx_dsb','jason_dsb','ycc']
        # 將列表中含'dsb'的篩選數來組成一個新列表
        # 方案一:for迴圈+if判斷+append
        new_l = []
        for name in l:
            if name.endswith('dsb'):
                new_l.append(name)
        print(new_l)
               
        # 方案二:生成式
        new_l1 = [name for name in l if name.endswith('dsb')]
        
        # 將字尾_dsb去掉
        new_l2 = [name.replace('_dsb','') for name in l]
        # 將字尾_dsb加上
        new_l3 = [name+'_dsb' for name in new_l2]
        
    # 2.字典生成式
    	 dic = {'name':'ycc','age':27,'gender':'male'}
         new_dic = {k:v for k,v in dic.items() if k != 'gender'}
         print(new_dic)
        
        items = [('name','ycc'),('age',27),('hobbies',['play',])]
        new_items = {k:v for k,v in items if k != 'hobbies'}
        print(new_items)
        
    # 3.集合生成式
         keys = ['name','age','hobbies']
         new_keys = {k for k in keys}
         print(new_keys)
        
    # 4.生成器生成式
        # g = (i for i in range(1,20) if i <18)
        # # 此刻g內部一個值也沒有
        #
        # print(next(g))
        # print(next(g))
        # print(next(g))
        # print(next(g))
    
        # sum()的使用方法
        # print(sum({1, 2, 3}))  # 要放可變型別
    
        # 將a.txt中的字元個數和算出來
        # with open('user.txt','rt',encoding='utf-8') as f:
            # 方法一:
            # res = 0
            # for line in f:
            #     res += len(line)
            # print(res)
    
            # 方法二:生成式
            # print(sum([len(line) for line in f]))
    
            # 方法三:
            # g = (len(line) for line in f)
            # 此刻內部一個值也沒有
            # print(sum(g))
            # 寫成一行就是:
            # print(sum((len(line) for line in f)))
            # 簡寫,可以去掉重複的括號
            # print(sum(len(line) for line in f))
                
    
  • 二分法

    # 必須是從小到大排序的數字列表
    # 如果沒有排序,用.sort()將其排序
    	nums = [-3,5,26,35,55,66,77,88,99,100]
        find_num = 88
        def binary_search(find_num,l):
            if find_num not in l:
                print('值不存在')
                return
            mid_index = len(nums) // 2
            mid_nums = l[mid_index]
            if find_num > mid_num:
                l = l[mid_index+1:]
                binary_search(find_num,l)
            elif find_num < mid_num:
                l = l[:mid_index]
                binary_search(find_num,l)
            else:
                print('find it')
        binary_search(find_num,nums)