­

Python中map函數的解釋和可視化

  • 2020 年 2 月 12 日
  • 筆記

先重溫一下迭代(Iteration)、迭代器對象(iterable)、迭代器(iterator )的概念:

Iteration是計算機科學的通用術語,它是指對一組元素執行一項操作,一次執行一個元素。一個很好的例子是循環 – 它適用於每個單獨的項目,直到整個項目集運行完畢為止。

Iterable是可以遍歷的對象(譯者註:在Python中所有東西都是object, 比如說變量,容器,類),iterable是可以產生iterator的object。

iterator是表示數據流的對象,它一次返回一個元素的數據。它還會記住其在迭代過程中的位置。本質上,它控制應如何迭代可迭代對象。

map()的用法

map()函數以迭代的方式將提供的功能應用於每個項目,結果是作為迭代器的map對象。語法:

map(func, *iterables)

如果沒有map(),我們將不得不編寫複雜的代碼以在多個項目上「循環」給定的函數。以一個整潔的小實驗為例:我們有一個10個單詞的列表。

test_list = ["effort", "circle", "yearly", "woolen", "accept", "lurker",              "island", "faucet", "glossy", "evader"]  

我們懷疑其中一些可能是abcderian(按字母順序出現的)。我們編寫一個函數is_abecedarian來檢查給定的單詞是否為abcderian:

def is_abecedarian(input_word):      index = 0      for letter in input_word[0:-1]:          if ord(input_word[index]) > ord(input_word[index + 1]):              return False          else:              index += 1      return True  

現在,我們想將函數應用於單詞列表,並創建一個將包含True和False值的新列表,以表明某些單詞是否確實是abcderian。

下面方法涉及初始化一個新列表,然後使用for循環遍歷列表元素:

value_list = []  for item in test_list:      value = is_abecedarian(item)      value_list.append(value)  

輸出:

[True, False, False, False, True, False, False, False, True, False]  

如果用map(),我們可以將上面的代碼簡化為一個簡潔的小代碼:

map(is_abecedarian, test_list)  

請注意map()不會返回列表,而是返回一個map對象。

譯者註:map()函數在python2中返回的是列表。

你可能很好奇哪個詞實際上是abcderian的字母-讓我們編寫這個問題的答案:

for item in test_list:      if is_abecedarian(item):          print(f"The word '{item}' is abecedarian. :)")      else:          print(f"The word '{item}' is not abecedarian. (")  

輸出:

The word 'effort' is abecedarian. :)  The word 'circle' is not abecedarian.  The word 'yearly' is not abecedarian.  The word 'woolen' is not abecedarian.  The word 'accept' is abecedarian. :)  The word 'lurker' is not abecedarian.  The word 'island' is not abecedarian.  The word 'faucet' is not abecedarian.  The word 'glossy' is abecedarian. :)  The word 'evader' is not abecedarian.  

我們還可以用可視化的方式形象地解釋,以幫助您更好地理解它:

這張圖也有助於定義 map 和mapping-我們可以使用Allen B. Downey在他的《Think Python》書中提供的定義:

映射操作(map):一種遍歷一個序列並對每個元素執行操作的處理模式。

映射(mapping):一個集合中的每個元素對應另一個集合中的一個元素的關係

將map()轉換為列表,元組和集合

由於map()不返回列表/元組/集合,因此我們需要採取額外的步驟來轉換生成的map對象:

def capitalize_word(input_word):      return input_word.capitalize()      map_object = map(capitalize_word, ['strength', 'agility', 'intelligence'])  test_list = list(map_object)  print(test_list)    map_object = map(capitalize_word, ['health', 'mana', 'gold'])  test_set = set(map_object)  print(test_set)    map_object = map(capitalize_word, ['armor', 'weapon', 'spell'])  test_tuple = tuple(map_object)  print(test_tuple)  

輸出:

['Strength', 'Agility', 'Intelligence']  {'Mana', 'Health', 'Gold'}  ('Armor', 'Weapon', 'Spell')  

將map()與Lambda表達式結合

Lambda表達式是對我們的工具庫的一個很好的補充:將Lambda表達式與map()代碼相結合可使您的Python程序更小,更精確。

Lambda表達式可以創建匿名函數,即未約定特定標識符的函數。相反,通過def關鍵字創建函數會將函數綁定到其唯一標識符(例如def my_function創建標識符my_function)。

但是,lambda表達式也有一系列限制:它們每個只能做一件事情,只能在一個地方使用,通常與其他功能結合使用。我們看看lambda表達式如何map()同時使用:

cities = ["caracas", "bern", "oslo", "ottawa", "bangkok"]      def capitalize_word(input_word):      return input_word.capitalize()      capitalized_cities = map(capitalize_word, cities)  

更簡潔的版本:

cities = ["caracas", "bern", "oslo", "ottawa", "bangkok"]    capitalized_cities = map(lambda s: s.capitalize(), cities)  

需要注意:map()和lambda表達式提供了凝聚多行代碼成一行的能力。儘管此功能非常出色,但我們需要牢記編程的黃金法則之一:代碼讀取比寫入更頻繁。這意味着map()和lambda表達式都可以提高代碼的簡潔性,但是卻犧牲了代碼的清晰度。遺憾的是,對於代碼的可讀性,實際上並沒有明確的指導方針- 隨着編程經驗的增長,大家將逐漸明白這一點。

使用map()遍歷字典

map()也非常適合遍歷字典

假設有一個包含蘋果,梨和櫻桃價格的字典,我們需要通過應用15%的折扣來更新價格表。方法如下:

price_list = {      "pear": 0.60,      "cherries": 0.90,      "apple": 0.35,  }      def calulates_discount(item_price):      return (item_price[0], round(item_price[1] * 0.85, 2))      new_price_list = dict(map(calulates_discount, price_list.items()))  

輸出:

{'pear': 0.51, 'cherries': 0.77, 'apple': 0.3}  

將map()與Lambda表達式組合遍歷字典

當開始組合多個功能時,編程特別有趣,一個很好的例子是map()配合使用和lambda表達式來遍歷字典。在下面的代碼中,我們初始化字典列表,並將每個字典作為參數傳遞給lambda函數。

list_of_ds = [{'user': 'Jane', 'posts': 18}, {'user': 'Amina', 'posts': 64}]    map(lambda x: x['user'], list_of_ds)  # Output: ['Jane', 'Amina']    map(lambda x: x['posts'] * 10, list_of_ds)  # Output: [180, 640]    map(lambda x: x['user'] == "Jane", list_of_ds)  # Output: [True, False]  

map()替代方法:列表解析

像所有技術/產品/方法等等一樣,一些Python開發人員認為map()函數在某種程度上不是Python風格(即未遵循應如何構建Python程序的精神和設計理念)。他們建議改用列表解析,比如:

map(f, iterable)  

變成

[f(x) for x in iterable]  

在速度和性能方面,map()與列表理析大致相等,因此不可能看到執行時間顯着減少 – 經驗豐富的Python開發者Wesley Chun在其演講<Python 103:Memory Model&Best Practices>中解決了這個問題,有興趣的同學可移步:https://conferences.oreilly.com/oscon/oscon2013/public/schedule/detail/29374

By:Denis Kryukov 翻譯:愛學習的衚衕學 https://blog.soshace.com/python-map-function-explained-visualized/