专业编程基础技术教程

网站首页 > 基础教程 正文

python散装笔记——69: Map 函数

ccvgpt 2025-02-14 22:25:46 基础教程 7 ℃

Parameter

Details

python散装笔记——69: Map 函数

function

用于映射的函数(参数个数必须与可迭代次数相同)(仅用于定位)

iterable

函数应用于可迭代元素中的每个元素(仅定位)

*additional_iterables

请参见 iterable,但数量不限(可选,仅定位)

1: map、itertools.imap 和 future_builtins.map 的基本用法

map函数是用于函数式编程的Python内置函数中最简单的一个。map() 对可迭代对象中的每个元素应用指定的函数:

names = ['Fred', 'Wilma', 'Barney']

Python 3.x Version ≥ 3.0

map(len, names) # map in Python 3.x is a class; its instances are iterable
# Out: 

与 Python 3 兼容的map包含在 future_builtins 模块中:

Python 2.x Version ≥ 2.6

from future_builtins import map # contains a Python 3.x compatible map()
map(len, names) # see below
# Out: 

或者,在 Python 2 中,可以使用 itertools 中的 imap 来获取生成器

Python 2.x Version ≥ 2.3

map(len, names) # map() returns a list
# Out: [4, 5, 6]
from itertools import imap
imap(len, names) # itertools.imap() returns a generator
# Out: 

可以明确地将结果转换为列表,以消除 Python 2 和 Python 3 之间的差异:

list(map(len, names))
# Out: [4, 5, 6]

可以用等效的列表理解或生成器表达式代替 map()

[len(item) for item in names] # equivalent to Python 2.x map()
# Out: [4, 5, 6]
(len(item) for item in names) # equivalent to Python 3.x map()
# Out:  at 0x00000195888D5FC0>

2: 映射可迭代器中的每个值

例如,可以取每个元素的绝对值:

list(map(abs, (1, -1, 2, -2, 3, -3))) # the call to `list` is unnecessary in 2.x
# Out: [1, 1, 2, 2, 3, 3]

匿名函数还支持映射列表:

map(lambda x:x*2, [1, 2, 3, 4, 5])
# Out: [2, 4, 6, 8, 10]

或将小数值转换为百分比:

def to_percent(num):
  return num * 100

list(map(to_percent, [0.95, 0.75, 1.01, 0.1]))
# Out: [95.0, 75.0, 101.0, 10.0]

或将美元兑换成欧元(给定汇率):

from functools import partial
from operator import mul

rate = 0.9 # fictitious exchange rate, 1 dollar = 0.9 euros
dollars = {'under_my_bed': 1000, 'jeans': 45, 'bank': 5000}

sum(map(partial(mul, rate), dollars.values()))
# Out: 5440.5

functools.partial 是一种固定函数参数的便捷方法,这样就可以用 map 代替 lambda 或创建自定义函数。

3: 映射不同迭代表的值

例如,计算多个迭代表中每 i 个元素的平均值:

def average(*args):
  return float(sum(args)) / len(args) # cast to float - only mandatory for python 2.x

measurement1 = [100, 111, 99, 97]
measurement2 = [102, 117, 91, 102]
measurement3 = [104, 102, 95, 101]

list(map(average, measurement1, measurement2, measurement3))
# Out: [102.0, 110.0, 95.0, 100.0]

根据 python 版本的不同,如果传递给 map 的可迭代次数超过一个,会有不同的要求:

  • 函数接受的参数必须与可迭代次数相同:
def median_of_three(a, b, c):
  return sorted((a, b, c))[1]

list(map(median_of_three, measurement1, measurement2))
# TypeError: median_of_three() missing 1 required positional argument: 'c'

list(map(median_of_three, measurement1, measurement2, measurement3, measurement3))
# TypeError: median_of_three() takes 3 positional arguments but 4 were given

当一个迭代停止时,映射也会停止:

import operator
measurement1 = [100, 111, 99, 97]
measurement2 = [102, 117]

# Calculate difference between elements
list(map(operator.sub, measurement1, measurement2))
# Out: [-2, -6]
list(map(operator.sub, measurement2, measurement1))
# Out: [2, 6]

4: 使用 Map 进行转置: 使用 "None" 作为函数参数(仅限 python 2.x)

from itertools import imap
from future_builtins import map as fmap # Different name to highlight differences

image = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

list(map(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(fmap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(imap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

image2 = [[1, 2, 3], [4, 5], [7, 8, 9]]

list(map(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8), (3, None, 9)] # Fill missing values with None
list(fmap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)] # ignore columns with missing values
list(imap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)] # dito

Python 3.x Version ≥ 3.0.0

list(map(None, *image))
# TypeError: 'NoneType' object is not callable

但有一种变通方法可以获得类似的结果:

def conv_to_list(*args):
  return list(args)

list(map(conv_to_list, *image))
# Out: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

5: 串联和并联映射

map() 是一个内置函数,这意味着无需使用 “导入 ”语句,它就可以在任何地方使用。如果你看看例 5,就会发现在使用 pretty print(导入 pprint)之前,我必须使用导入语句。因此,pprint 并不是一个内置函数

串联映射

在这种情况下,迭代的每个参数都会以升序作为映射函数的参数。当我们只有一个可迭代表需要映射,而映射函数只需要一个参数时,就会出现这种情况。

示例 1

insects = ['fly', 'ant', 'beetle', 'cankerworm']
f = lambda x: x + ' is an insect'
print(list(map(f, insects))) # 在可迭代器的每个项上执行由 f 定义的函数

结果是

['fly is an insect', 'ant is an insect', 'beetle is an insect', 'cankerworm is an insect']

示例 2

print(list(map(len, insects))) # the len function is executed each item in the insect list

结果是

[3, 3, 6, 10]

并行映射

在这种情况下,映射函数的每个参数都会从所有迭代表(每个迭代表一个)中并行提取。因此,所提供的可迭代次数必须与函数所需的参数数一致。

carnivores = ['lion', 'tiger', 'leopard', 'arctic fox']
herbivores = ['african buffalo', 'moose', 'okapi', 'parakeet']
omnivores = ['chicken', 'dove', 'mouse', 'pig']

def animals(w, x, y, z):
  return '{0}, {1}, {2}, and {3} ARE ALL ANIMALS'.format(w.title(), x, y, z)

示例 3

# 参数太多
# 这里可以看到,map 试图从四个迭代表中的每个迭代表中各传递一个项目给 len。这导致 len 抱怨 输入的参数过多
print(list(map(len, insects, carnivores, herbivores, omnivores)))

结果是

TypeError: len() takes exactly one argument (4 given)

示例 4

# 参数太少
# 这里要注意的是,map 应该对 insects 的单个元素逐个执行 animal。但是,当 animals 只得到一个参数时,它就会抱怨,因为它本来以为会得到四个参数。
print(list(map(animals, insects)))

结果是

TypeError: animals() missing 3 required positional arguments: 'x', 'y', and 'z'

示例 5

# 在这里,地图为 w、x、y、z 提供了整个列表中的一个值
import pprint
pprint.pprint(list(map(animals, insects, carnivores, herbivores, omnivores)))

结果是

['Fly, lion, african buffalo, and chicken ARE ALL ANIMALS',
'Ant, tiger, moose, and dove ARE ALL ANIMALS',
'Beetle, leopard, okapi, and mouse ARE ALL ANIMALS',
'Cankerworm, arctic fox, parakeet, and pig ARE ALL ANIMALS']

最近发表
标签列表