1. 程式人生 > >day012生成器函式、生成器表示式、列表推導式

day012生成器函式、生成器表示式、列表推導式

本節主要內容

  • 生成器和生成器表示式

  • 列表推導式

一、生成器

  • 生成器實質就是迭代器

1、python中獲取生成器的三種方式:

* 通過生成器函式
* 通過生成器表示式
* 通過資料的轉換獲取生成器

1.生成器函式

**fe1:**
'''python
def func():
    print("111")
    yield 222
ret = func()        #generator 生成器
print(ret)  #結果:<generator object func at 0x10567ff68>
'''
  •  

    函式裡面有yield,就是生成器函式

    * yield的作用

      ① yield + 返回值 (是一個類似 return 的關鍵字,迭代一次遇到yield時就返回yield後面(右邊)的值。
      (生成器函式不要出現return)
      ② 重點是:下一次迭代時,從上一次迭代遇到的yield後面的程式碼(下一行)開始執行。(分段執行)
      ③  生成器函式被呼叫的時候. 返回生成器
    
      def func():
          yield
      g = func() - 得到生成器

     

2.生成器的用法

  **生成器的用法和迭代器基本一致**
  *  __next__() 開始執行生成器 .  執行到yield. 直到沒有yield. 丟擲StopIteration

  * send() 可以給上一個yield傳值,send()不可以在第一個位置和最後一個位置出現

fe:

'''python
def func():
    print("水餃")
    a = yield "大餡水餃"
    print("a=", a)
    print("燒餅")
    b = yield "武大郎燒餅"
    print("b=",b)
    print("老婆餅")
    c = yield "只要老婆不要餅"
    print("c=", c)

gen = func() # 生成器
print("返回值是:", gen.__next__())
print("返回值是:",gen.send("混沌面")) #  和__next__()一樣也是向下找yield. 給上一個yield傳值
print("返回值是:",gen.send("胡辣湯")) #  和__next__()一樣也是向下找yield. 給上一個yield傳值
print("返回值是:",gen.send("馬拉")) #  和__next__()一樣也是向下找yield. 給上一個yield傳值

 send()不可以在第一個位置和最後一個位置出現
 最後的yield後的程式碼是可以執行的但是會報錯. StopIteration
 '''

2、生成器的三大特點(同迭代器)

 1. 省記憶體
 2. 惰性機制,  不訪問__next__() 就沒有值.
 3. 只能向前. 不能反覆.

二、各種推導式(簡單)

  • 列表推導式 語法: [ 結果 for迴圈(可多個) if判斷] 就三種,其中if可有可無

  • 字典推導式 語法: { key:value for迴圈 if判斷}

  • 集合推導式 語法: { key for迴圈 if判斷}

  • 切記沒有元組推導式,推導式指的是可以迭代的,元組不可迭代

fe1:

'''python
列表推導式 快速的簡單的建立一個列表
lst = ["python全棧%s期" % i for i in range(1, 17)]
語法: [結果 for迴圈 if判斷]
'''

fe2:

'''python
成列表: 1-20 所有的奇數的2次方
print([ i*i for i in range(1,21) if i % 2 == 1])
'''

fe3:

'''python
# [3,6,9]  已知
# [(1,2,3), (4,5,6), (7,8,9)]
# lst = [3,6,9]
# new_lst = [(el-2, el-1, el) for el in lst]
'''

fe4:

'''python
尋找名字中帶有兩個e的⼈的名字 name.count("e") == 2
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
     ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

lst = [name for el in names for name in el if name.count("e") == 2]
print(lst)

**此處使用到了兩層for迴圈**
'''

fe5:字典中的推導式

'''python
dic = {"張無忌":"趙敏", "楊過":"小龍女", "郭靖":"黃蓉"}
# 把字典中的key和value互換
# dic = {"趙敏":"張無忌", "小龍女":"楊過", "黃蓉":"郭靖"}
dic1 = { v:k for k, v in dic.items()}  # 強化記憶,理解
print(dic1)

dic2 = { dic[k]:k for k in dic} # 強化記憶,理解
print(dic2)

'''

fe6:集合中的推導式

'''python
集合推導式 # 不可變. 不重複, 無序
{結果 for迴圈 if判斷}
s = {i*"胡辣湯" for i in range(10)}
print(s)
'''

三、生成器表示式

  • 生成器表示式 (結果 for迴圈 if判斷) => 生成器表示式

1、特點: 本質是迭代器. next()

1. 省記憶體
2. 惰性機制
**生成器只有在訪問時才取值,你找他要,他才給你值,
不找是不會執行的,面試題就喜歡出這裡,**
3. 只能向前

2、例項

1、惰性機制的體現

fe1:
**list內建了for迴圈**
'''python
g = (i for i in range(10))
#* s = {1,2 , 3, 4, 5} => list(s) => list = [1,2,3,4,5,]
#上面的轉換說明了list裡面存在,for迴圈
print(list(g)) # 把傳遞進來的資料轉化成列表.  裡面包含了for迴圈
# list() => for=> __iter__() ==> __next__()

print(list(g)) # 上一次已經拿沒了
print(g.__next__()) # 已經沒有資料了
for el in g:
    print(el)
for el in g: # 已經沒有資料了 惰性機制-> 只能往前
print(el)
'''
fe2:重要的面試題
'''python
def func(): # 生成器函式
    print(111)
    yield 222

g = func() #  生成器 -> 沒有執行過__next__()
g1 = (i for i in g) # 生成器表示式. 也沒有__Next__()
g2 = (i for i in g1) # 生成器表示式. 也沒有__Next__()
#到此為止, 沒有人拿過值

**需要知道的知識點:list裡內建了for迴圈**

print(list(g2)) # 111 [222] #
print(list(g)) #  []
print(list(g1)) # []

**關鍵點:生成器表示式,一旦被拿完了,就沒有了,直白說,一旦被人拿了,就沒了。**
'''

3、yield from

⼩坑

yield from是將列表中的每⼀個元素返回. 所以. 
如果寫兩個yield from 並不會產⽣交替的效果

fe1:

'''python
def gen():
    lst = ["⿇花藤", "胡辣湯", "微星牌餅鐺", "Mac牌鍋鏟"]
    yield from lst # 把列表中的每一個元素返回
    # yield  lst[0] # 等同於下面四個命令的組合
    # yield  lst[1]
    # yield  lst[2]
    # yield  lst[3]

g = gen() # 生成器函式 -> 獲取生成器
for el in g:
    print(el)
    '''

fe2:

'''python
def gen():
lst = ["⿇花藤", "胡辣湯", "微星牌餅鐺", "Mac牌鍋鏟"]
lst2 = ["餅鐺還是微星的好", "聯想不能煮雞蛋", "微星就可以", "還可以烙餅"]
yield from lst  # 先迴圈列印lst,再列印lst2
# yield lst[0]
# yield lst[1]
# yield lst[2]
# yield lst[3]
yield from lst2
# yield lst2[0]
# yield lst2[1]
# yield lst2[2]
# yield lst2[3]

g = gen() # 獲取生成器
for el in g: # 從生成器獲取資料
    print(el) # 列印
'''