1. 程式人生 > >列表推導式+lambda表示式的激情

列表推導式+lambda表示式的激情

Python這麼優雅的語言,我也是醉了......

事情由一段程式碼引發,請看:

上述的列表推導式+lambda表示式+for迴圈,他們碰撞出來的結果搞的人暈頭轉向,咱們逐步來分析一下他們到底是個什麼鬼。

lambda表示式可以表示成:

def func(x):
    return x*i

加上for迴圈:

for i in range(10):
    def func(x):
        return x*i

加上列表推導式:  # 註釋一

li = []

def funcs():
    for i in range(10):
        def func(x):
            return x*i
        li.append(func)
    return li
funcs()
到此,就可以看清楚他的結構了,funcs函式裡面形成了一個閉包

閉包的兩個特性:

①、內部函式使用外部函式的變數(不對外部函式的變數進行重新賦值)

②、外部函式 return 內部函式的函式名(其實是返回內部函式的記憶體地址)

對上面的函式進行簡化:去掉for迴圈,使用單個變數代替,去掉 列表 li 直接返回內部函式名,它就變成了下面這個樣子

def funcs():
    i=9  # 定義了變數,也稱為內部函式的環境變數,它不會改變,不被外界影響

    def func(x):
        return x*i  # 使用了外部函式的變數

    return func  # 返回了內部函式

簡單理解:閉包 = 內部函式 + 環境變數

閉包的特性:當內部函式返回的時候,會把連同內部函式定義時候的環境變數一同返回

瞭解了閉包,在來看結果為什麼全都是18,而不是預期結果:

①區分內部函式的定義和呼叫:

當我們只到是定義了外部和內部函式,呼叫了外部函式,並未呼叫內部函式,也就是到註釋一

for迴圈的作用就是建立10個函式,最後 i 的取值是9

所以我們獲得了類似下面的圖譜:

當我們進行內部函式呼叫的時候,此時的情形是:

有一個包含10個函式的列表,變數 i=9

再加上閉包的特性,i 會隨著內部函式的一同返回,所以呼叫依次內部函式的時候,情形就成了下面這樣:以呼叫第1個函式為例

所以結果就成了 2 * 9 = 18

再呼叫別的內部函式都是如此邏輯。

知乎中此問題的回答者 @Op小劍 提到了延遲繫結

匿名函式的 i 並不是依次順序指向0,1,2,...的,因為在迭代的過程中,建立匿名函式→建立完成後→才去找i 指向的值。

對上圖做了很好的詮釋微笑

當我們將表示式修改為下面的樣子,預期結果就出現了:

li = []

def funcs():
    for i in range(10):
        def func(x, i=i):  # 給內部函式傳參, i 是內部函式的區域性變數,當所有內部函式定義完畢,i 的值也變成了一個列表(range(10))
            return x*i  # 呼叫的時候其實是呼叫的內部函式的值
        li.append(func)
    return li

for func in funcs():
    func(2)

修改到列表推導式+lambda表示式就是下面的情況:

funcs = [lambda x, i=i: x*i for i in range(10)]
for func in funcs:
    print(func(2))

此時呼叫的情形就像下面的圖譜:

到此,此問題就分析結束了,涉及到的變數作用域,就不分析了,大家可以自行百度去理解。

相關推薦

列表推導+lambda表示式激情

Python這麼優雅的語言,我也是醉了......事情由一段程式碼引發,請看:上述的列表推導式+lambda表示式+for迴圈,他們碰撞出來的結果搞的人暈頭轉向,咱們逐步來分析一下他們到底是個什麼鬼。lambda表示式可以表示成:def func(x): return

python迭代器-生成器-列表推導-生成器表示式-day11-12

生成器Generator    生成器函式一個包含yield關鍵字的函式就是一個生成器函式。yield可以為我們從函式中返回值,但是yield又不同於return,return的執行意味著程式的結束,呼叫生成器函式不會得到返回的具體的值,而是得到一個可迭代的物件。每一次獲取這個可

列表推導+lambda+for(Python)

以下程式碼將輸出什麼?def testFun(): temp = [lambda x : i*x for i in range(4)] return temp for everyLambda in testFun(): print (everyLam

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

本節主要內容 生成器和生成器表示式 列表推導式 一、生成器 生成器實質就是迭代器 1、python中獲取生成器的三種方式: * 通過生成器函式 * 通過生成器表示式 * 通過資料的轉換獲取生成器 1.生成器函式 **fe1:**

列表推導,生成器表示式

示例:使用for迴圈從1列印到100的數 l1 = [] for i in range(1,101): l1.append(i) print(l1) 1、列表推導式 # 凡是用列表推導式能構建的資料,# python程式碼都可以構建,列表推導式不能構建的資料,python程式碼亦可以可

python3:列表推導,生成器表示式,字典推導 三種用法講解

列表推導式 任務: 我們有個任務是提取0—20的奇數位. 1.首先我們想到的是用for迴圈加if做到,如下: b=[] for i in range(21): if i%2==1: b.append(i) print(b) 2.懂list 也可以想

python day12 ——1.生成器2.生成器表示式 3.列表推導

一、生成器  什麼是生成器. 生成器實質就是迭代器。  在python中有三種方式來獲取生成器:  1. 通過生成器函式。 2. 通過各種推導式來實現生成器 。 3. 通過資料的轉換也可以獲取生成器。   1.首先, 我們先看一個很簡單的函式:

列表推導lambda的結合

def fun():     # return (lambda x: x * i for i in range(4))  # 結果是[0,2,4,6]     return [lambda x: x * i for i in range(4)]

生成器、列表推導和生成器表示式

生成器 生成器特點: 1. 生成器本質上迭代器 2. 生成器是自己用程式碼建立的 獲取生成器的兩種方式: 1. 生成器函式 2. 生成器表示式   yield 下面來看一個例子 1 def func(): 2 print(111) 3 yield 66

python中:生成器表示式列表推導的比較

l = [2, 3, 5, 7] l2 = [x ** 2 + 1 for x in l] it = iter(l2) print(next(it)) # ? l[1] = 30 print

python列表推導中使用if-else

python列表推導式 if-else 今天在處理自動化郵件數據時碰到數據行中包含字符串後,從hive中拿到的整數型數據自動轉化成了浮點數,嚴重影響美觀性。因此想到了用列表推導式來做轉化,將其中的數字型數據全部轉化為整型,而字符型數據保留原樣。列表推導式總共有兩種形式:①[x for x in data

Python3的列表推導

odin utf int pri 列表推導式 列表 python return python3 # -*- coding: utf-8 -*- li = [1,2,3,4,5,6,7,8,9]print ([x**2 for x in li]) print ([x**2 f

列表推導

引用 spa for 循環 字符 元素 字符串 書寫 列表推導 color 1-100 的平方 [x * x for x in range(100)] 書寫習慣為從右至左 依次寫出range(100) 然後for 循環 然後x * x 然後放進List 生成字符串 ["T

python列表推導

lai com expr 實際應用 http port ack ron dig python基礎——列表推導式 1 列表推導式定義 列表推導式能非常簡潔的構造一個新列表:只用一條簡潔的表達式即可對得到的元素進行轉換變形 2 列表推導式語法 基本格式如下:

day4-列表推導與生成器表達

圖片 表達 class bsp 技術 com 列表推導 png src 用列表推導式變成一行: 列表解析: 列表解析最終生成的是一個真實存數據的列表。 2,生成器表達式: next一次執行一次。 day4-列表推導式與生成器表達式

六 三元表達列表推導、生成器表達

pan abc 一次 pri 聲明 優點 express 推導 next 一 三元表達式 二 列表推導式 三 生成器表達式 一 三元表達式 1 name=input(‘姓名>>: ‘) 2 res=‘abc‘ if name == ‘l

列表推導----生成器表達

odin 使用 結果 with open append split() spl eno enc 列表推導式:   基本形式: [表達式 for 參數 in 可叠代對象] 或者 [表達式 for 參數 in 可叠代對象 if 條件]   實例:

4-4日 列表推導,生成器推導

兩種模式 span 一個 列表 bsp 字符 ali eva pos 1,列表推導式就是在列表中進行for 循環if語句判斷,最多兩個for,一個if判斷 #求1到30 被3整除的數的平方 li = [i*i for i in range(1,31)if i%3 == 0

(列表推導,生成器表達,內置函數)

全局局部變量 通過 實例 app compile 根據 重要 字符編碼 初始 一,列表生成式 示例一: 生成1~100的列表 生成1~100的列表 1 2 3 4 5 li = [] for i in range(1,101): li.appen

三元表達列表推導、生成器表達、遞歸、內置函數、匿名函數

改變 現在 lose 知識庫 數據結構實現 結果 VM 情況 www. 一、三元表達式 name=input(‘姓名>>: ‘) res=‘SB‘ if name == ‘alex‘ else ‘NB‘ print(res) 二、列表推導式和生成器表達式