自我实现map()

时间:2018-12-23 13:26:03

标签: python python-3.x

我必须自己实现可以获得多个功能的新map()。

我写了这段代码:

def map(iterable, *callbacks):
    temporary = []
    callbacksList = list(callbacks)
    for func in callbacksList:
        for item in iterable:
             temporary.append(func(item))
        callbacksList = callbacksList[1:]
        iterable = temporary
        temporary = []
    return iterable

在这种情况下,代码可以正常工作

c = "hello"
print(map(c,str.upper,ord,chr)) # => ['H','E','L','L','O']

但在这种情况下:

c = "hello"
print(map(c,str.upper,chr,ord))

我收到错误消息“需要整数(类型为str)”-由于chr函数获取的是str而不是int。

我不知道如何调整我的代码以同时适用于两种情况和更通用。 谢谢帮手。

2 个答案:

答案 0 :(得分:2)

由于您的回调似乎是一个接一个地应用,为什么不将其设为生成器并交换两个for循环(因此您的iterable也可以是生成器):

def map(iterable, *callbacks):
    for item in iterable:
        for f in callbacks:
            item = f(item)
        yield item

list(map("hello", str.upper, ord, chr))
# ['H', 'E', 'L', 'L', 'O']

但是,就像您的代码一样,这要求每个函数的输出也是以下函数的有效输入。如果不是这种情况,则可以忽略所有引发异常的函数:

def map2(iterable, *callbacks):
    for item in iterable:
        for f in callbacks:
            try:
                item = f(item)
            except (TypeError, ValueError):  # might want to be more generic than this, depending on your functions
                pass
        yield item

list(map2("hello", str.upper, chr, ord))
# [72, 69, 76, 76, 79]

但这实际上取决于您的用例,在这种情况下,什么是正确的操作。

答案 1 :(得分:2)

您实际上是组成您的回调列表;你的电话

"key2" : "income"

应该等效于map(c, str.upper, ord, chr) 。但是,您的另一尝试

map(c, lambda x: chr(ord(str.upper(c))))

等效于map(c, str.upper, chr, ord) ,而map(c, lambda x: ord(chr(str.upper(c)))根本没有定义; ord(chr('x'))不能将字符串作为参数。

也就是说,您可以通过首先组成函数,然后使用内置的chr应用组成的函数来简化定义。

map

您还可以使用def map(iterable, *callbacks): # The identity function i = lambda x: x is the identity for function composition. # That is, f(i(x)) == i(f(x)) == f(x) f = lambda x: x for g in callbacks: # The g=g is necessary due to how Python handles name lookups f = lambda x, g=g: g(f(x)) return map(f, iterable) 函数执行合成。

functools.reduce

一个重要的注意事项:由于在调用链中插入了额外的匿名函数,并且函数调用的成本较高,因此这种编程风格在Python中不是很有效。