2012-02-09 60 views
0

有人可以解釋下面的python代碼是如何工作的嗎?該代碼正在讀取一系列整數,它們被排列爲3元組。在Python中使用map讀取一個整數序列

inverted_list = map(lambda i: (int(numbers[2 + 3*i]), 
          float(numbers[3 + 3*i]), 
          float(numbers[4 + 3*i])) 
        ,range(0, (len(numbers) - 2)/3)) 

究竟如何地圖和lambda作品?拉姆達真的需要嗎?

謝謝。

回答

1

沒有,是不是真的在這裏需要拉姆達,這也可以寫成:

inverted_list = [(int(numbers[2 + 3*i]), 
        float(numbers[3 + 3*i]), 
        float(numbers[4 + 3*i])) for i in range(0, (len(numbers) - 2)/3] 

我不打算進入索引的數學位,因爲我對我今天的第一杯咖啡,只有我,但什麼map這樣做,是對一個序列應用一個函數,用每個元素的函數結果生成一個新的序列。 lambda是函數,在這種情況下,從您的數字創建一個元組。該序列是range表達式,它爲您提供可在索引表達式中使用的i值列表(例如3 + 3*i)。

您的代碼片段@gnibbler的版本和我顯示的是現代 python。這不在python 1.5中 - 所以我們使用了map,reduce,zip和其他「功能性」高階操作。我個人非常喜歡他們,但我猜這個註定會被大部分任務所取代 - 列表解析在這種情況下更具表現力!

1

這大致相當於這個列表理解。使用地圖與拉姆達會跑的比列表理解慢一點,雖然

inverted_list = [((int(numbers[2 + 3*i]), float(numbers[3 + 3*i]), 
       float(numbers[4 + 3*i])) for i in range(0, (len(numbers) - 2)/3)] 

擊敗我,爲什麼你會乘i 3無處不在,雖然,

inverted_list = [((int(numbers[i]), float(numbers[1+i]), 
       float(numbers[2+i])) for i in range(2, len(numbers), 3)] 
+0

因爲前2個數字不是序列的一部分。我認爲它有效地運行一個循環,從系列的第三個元素開始。我只是困惑,無論是地圖/ lambda在這裏執行任何其他操作。 – 2012-02-09 09:18:56

1

它創建了一個列表

(numbers[2],numbers[3], numbers[4], numbers[2 + 3],numbers[3 + 3], numbers[4 + 3], ...., numbers[2 + 3*((len(numbers) -2)/3)],numbers[3 + 3*((len(numbers) -2)/3)], numbers[4 + 3*((len(numbers) -2)/3)] 

映射範圍:

range(0, (len(numbers) - 2)/3) 

與拉姆達元組。

一種方法是使用; 2,列表理解和迭代範圍開始,大小爲3步:

[(int(numbers[i]), float(numbers[i + 1]), float(numbers[i + 2])) for i in range(2,len(numbers), 3)] 
1

您已經擁有了解釋更好或更現代的方式來表達這個答案,但我想準確地展示了lambda和map在更多基本特性方面所做的工作。首先,這裏是你的例子:

inverted_list = map(lambda i: (int(numbers[2 + 3*i]), 
           float(numbers[3 + 3*i]), 
           float(numbers[4 + 3*i])) 
        ,range(0, (len(numbers) - 2)/3)) 

爲了使事情更清楚一點,我將分開的地圖參數。這相當於;所有我已經改變是計算每個參數在一個單獨的聲明映射:

func = lambda i:(int(numbers[2 + 3*i]), 
       float(numbers[3 + 3*i]), 
       float(numbers[4 + 3*i])) 
sequence = range(0, (len(numbers) - 2)/3) 
inverted_list = map(func, sequence) 

lambda僅僅是爲了表達一種表達式中的簡單功能的方式。我們可以在不改變的效果與普通函數替換它:

def func(i): 
    return (int(numbers[2 + 3*i]), 
      float(numbers[3 + 3*i]), 
      float(numbers[4 + 3*i])) 
sequence = range(0, (len(numbers) - 2)/3) 
inverted_list = map(func, sequence) 

map是所謂的「高階函數」,即取另一個函數作爲參數的函數。通過sequence每個項目map將循環,調用func與該項目作爲參數,採取任何函數返回,並將其添加到一個新的列表。*

如果你想要做同樣的事情,沒有高階函數或發電機表達式,你可以寫這個了很長的路要走:

def func(i): 
    return (int(numbers[2 + 3*i]), 
      float(numbers[3 + 3*i]), 
      float(numbers[4 + 3*i])) 
sequence = range(0, (len(numbers) - 2)/3) 
inverted_list = [] 
for item in sequence: 
    inverted_list.append(func(item)) 

拉姆達的好處是,你可以在一個表達的東西,否則將需要你想點之前引入臨時變量,可能在聲明函數某種方式表達使用它。 map的好處是相似的,你可以在一個表達式中寫一些否則會需要臨時變量和循環的東西。

(*)從Python 3開始,map實際上會返回一個迭代器,而不是一個列表。