1. 程式人生 > >Python 入門基礎11 --函數基礎4 叠代器、生成器、枚舉類型

Python 入門基礎11 --函數基礎4 叠代器、生成器、枚舉類型

不依賴 ria factorial 完成 func data- except spl 技術

今日目錄:

  • 1.叠代器
  • 2.可叠代對象
  • 3.叠代器對象
  • 4.for循環叠代器
  • 5.生成器
  • 6.枚舉對象

一、叠代器:

循環反饋的容器(集合類型)
每次重復即一次叠代,並且每次叠代的結果都是下一次叠代的初始值
技術分享圖片
l = [1, 2, 3]
count = 0
while count<len(l):
    print(l[count])
    count += 1
View Code
1.1 為什麽要有叠代器?
字符串、列表、元組可以通過索引的方式叠代取出其中包含的元素
字典、集合、文件等類型,沒有索引,只有通過不依賴索引的叠代方式才能取值,即叠代器

二、可叠代對象

2.1 什麽是可叠代對象
可叠代對象指的是內置有__iter__()方法的對象,即obj.__iter__()
技術分享圖片
str,list,tuple,dict,set,range(),file,叠代器對象,enumerate(),生成器都是可叠代對象,即:
[].__iter__()
{}.__iter__()
().__iter__()
{1,2}.__iter__()
   ......
View Code

三、叠代器對象

3.1 什麽是叠代器對象
可叠代對象通過調用__iter__()方法得到叠代器對象
叠代器對象可以不依賴索引取值(一次從容器中取出一個值) 
叠代器對象都有__next__方法,且通過該方法獲取容器中的值,獲取規則,從前往後一次一個
3.2 有哪些叠代器對象
文件類型、enumerate()、生成器是叠代器對象
open(‘a.txt‘).__iter__()
open(‘a.txt‘).__next__()
ps:    
    1.叠代器對象去一個值就少一個值
    2.取完了再取會報錯  --> 可通過try對異常進行捕獲,並處理
    3.上一個叠代器對象叠代取值完畢後,就取空了,如果要再取值,要重新生成叠代器對象
    4.叠代器對象不能求長度(內部值的個數)
    5.叠代器對象一定是可叠代對象,而可叠代對象不一定時叠代器對象
技術分享圖片
# 叠代器對象
iter_obj = st1.__iter__
() print(iter_obj) # <set_iterator object at 0x0000025B85231CF0> print([1, 2, 3].__iter__()) # <list_iterator object at 0x0000017694B0B860> # 叠代器對象去一個值就少一個值 print(iter_obj.__next__()) # 9 print(iter_obj.__next__()) # 2 print(iter_obj.__next__()) # 3 print(iter_obj.__next__()) # 4 print(iter_obj.__next__()) # 7 # print(iter_obj.__next__()) # 7 # 異常 StopIteration
View Code 技術分享圖片
# 叠代器無法求長度(內部值的個數)
while True:
    try:  
        val = iter_obj2.__next__()
        print(val)
    except StopIteration:
        break
View Code

四、for 循環叠代器

自帶異常處理的while循環,自動獲取被叠代的對象的叠代器對象
原理:
    1.執行in後面對象的dic.__iter__()方法,得到一個叠代器對象iter_dic
    2.執行next(iter_dic),將得到的值賦值給k,然後執行循環體代碼
    3.重復過程2,直到捕捉到異常,StopIteration,結束循環
叠代器的優缺點:
    1.優點
        提過一種統一的、不依賴於索引的叠代方式
        惰性計算,節省內存
    2.缺點
        無法獲取長度(只有在next完畢才知道到底有幾個值)
        一次性的,只能往後走,不能往前退
技術分享圖片
# for 循環叠代器,自帶異常處理的while循環,自動獲取被叠代的對象的叠代器對象
iter_obj = st1.__iter__()
for item in iter_obj:
    print(item)
print(----------------華麗的分割線-----------------------------------------------)

for item1 in st1:
    # 自動完成for item in st1.__iter__()
    # 自動完成異常處理
    print(item1)
View Code

五、生成器

包含yield關鍵字的函數就是生成器
def fn():
    yield ‘good‘
    
該函數名()得到的是生成器對象,且不會執行函數體

生成器的應用案例
當訪問的數據資源過大,可以將數據用生成器處理,一次只獲取所有內容的一條資源
技術分享圖片
def g_fn():
    print("!!!!!!!!!!!!!!!!!!!!")
    yield 第一個

    print(@@@@@@@@@@@@@@@@@@@@@)
    yield 第二個

    print(#####################)
    yield 第三個

    print($$$$$$$$$$$$$$$$$$$$$)
    yield 第四個


g_obj = g_fn()

# 在函數內部執行一次,在遇到下一個yield時停止,且可以拿到yield的返回值
r1 = g_obj.__next__()
print(r1)

# 從上一次停止的地方繼續往下走,再遇到下一個yield的時候停止,且可以拿到yield的返回值
r2 = g_obj.__next__()
print(r2)

r3 = g_obj.__next__()
print(r3)
View Code 技術分享圖片
# 重新定義一個range()生成器

def my_range(min, max, step=1):
    # min, max = max, min
    tag = min
    while True:
        if tag >= max:
            break
        yield tag
        tag += step


range_obj = my_range(5, 10, 1)

for i in range_obj:
    print(i)
View Code

六、枚舉對象

通過for循環叠代器循環遍歷可叠代對象,需要知道叠代的索引

作業:
技術分享圖片
# 1.用生成器完成自定義range方法,可以完成系統range的所有功能


def my_range(min, max= 0, step=1):

    if step > 0:  # 步長為正的
        if max == 0:  # 如果最大值為 0 --> my_range(10)
            min, max = max, min
        tag = min
        while True:
            if tag >= max:
                break
            yield tag
            tag += step

    elif step < 0:  # 步長為負的
        tag = min
        if min > max:
            while True:
                if tag <= max:
                    break
                yield tag
                tag += step

    else:   # 第三個參數不能是 0
        print("第三個參數不能是 0 !")


range_obj1 = my_range(10, 1, -2)
range_obj2 = my_range(10)  # --------可以用
range_obj3 = my_range(2, 10)  # -----可以用
range_obj4 = my_range(2, 10, 2)  # --可以用


"""
for i in range_obj1:
    print(i)
"""
View Code 技術分享圖片
# 2.用生成器完成自定義enumerate方法,也可以為可叠代對象提供索引支持

# ls = [4, 3, 7, 5, 9]
ls = {1,2,3,4,5,6}

def my_enumerate(data):
    count = 0
    for i in data:
        yield (count, i)
        count += 1


"""
for i, v in my_enumerate(ls):
    print(i, v)
"""
View Code 技術分享圖片
# 3.用生成器完成獲取階乘得方法,第一次next得到1的階乘,第二次next得到2的階乘,依次類推,

# 直接for循環,可以依次得到指定範圍內得所有階乘,eg:factorial(10),可以得到1~10之間的10個階乘

def my_factorial(num):
    tag = 1
    for i in my_range(1, num+1):
        tag *= i
        yield tag

factorial_obj = my_factorial(10)

for i in factorial_obj:

    print(i)
"""
1
2
6
24
120
720
5040
40320
362880
3628800
"""
View Code

Python 入門基礎11 --函數基礎4 叠代器、生成器、枚舉類型