如何在Python中创建自己的map()函数

问题描述 投票:0回答:3

我正在尝试在 python 中创建内置的 map() 函数。 这是可以尝试的:

def mapper(func, *sequences):


   if len(sequences) > 1:
       while True:
          list.append(func(sequences[0][0],sequences[0][0],))
       return list

return list

但我真的陷入困境,因为如果用户给出例如 100 个参数,我该如何处理这些

python list map-function
3个回答
4
投票

调用函数时使用星号

*

def mapper(func, *sequences):
       result = []
       if len(sequences) > 0:
           minl = min(len(subseq) for subseq in sequences)
           for i in range(minl):
              result.append(func(*[subseq[i] for subseq in sequences]))
       return result

这会产生:

>>> import operator
>>> mapper(operator.add, [1,2,4], [3,6,9])
[4, 8, 13]

通过使用星号,我们将可迭代对象解压为函数调用中的单独参数。

请注意,这仍然不完全等效,因为:

  1. sequences
    应该是iterables,而不是本身的列表,所以我们不能总是索引;和
  2. python-3.x
    的结果也是一个 iterable,所以不是列表。

一个更像

map
函数将是:

def mapper(func, *sequences):
    if not sequences:
        raise TypeError('Mapper should have at least two parameters')
    iters = [iter(seq) for seq in sequences]
    while True:
        yield func(*[next(it) for it in iters])

但请注意,大多数 Python 解释器会实现比 Python 代码更接近解释器的

map
,因此使用内置
map
肯定比编写自己的更有效。

N.B.:最好不要使用

list
set
dict
等变量名称,因为这些名称将覆盖(此处为本地)对
list
类型的引用。因此,像
list(some_iterable)
这样的调用将不再有效。


1
投票

将序列或序列逻辑的组合部分分开,更容易阅读和理解。

def mapper(func, *args):
    for i in zip(*args):
        yield func(*i)

这里我们使用内置的Python

zip
如果您想将其完全替换为您自己的实现,请将
zip
替换为以下
zipper
函数

def zipper(*args):
    for i in range(len(args[0])):
        index_elements = []
        for arg in args:
            index_elements.append(arg[i])
        yield positional_elements

0
投票

Willem(带有 yield

)之前的 
回答提高了
RuntimError
;这不起作用。

Pardhu之前的回答试图将问题分解为

mapper
zipper
。这很好,但它没有合理或有效的
zipper
实现,也没有更紧密地匹配 Python 的原生
zip
。这个答案使用了更合理的
zipper
实现,它更正确地使用了迭代。

def zipper(*iterables):
    # Ref: https://stackoverflow.com/a/77297966
    iterables = [iter(iterable) for iterable in iterables]
    try:
        while True:
            yield tuple(next(iterable) for iterable in iterables)
    except RuntimeError:  # Note: StopIteration is not raised.
        # Note: `exc.args[0] == 'generator raised StopIteration'` can optionally be confirmed.
        pass


def mapper(func, *iterables):
    return (func(*i) for i in zipper(*iterables))  # Note: `zipper` aims to match `zip`.

使用示例:

> mapper(lambda *i: sum(i), range(11, 15), range(20, 30))
<generator object mapper.<locals>.<genexpr> at 0x7ffa1a448900>

> list(_)
[31, 33, 35, 37]
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.