我必须自己实现可以获得多个功能的新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。
我不知道如何调整我的代码以同时适用于两种情况和更通用。 谢谢帮手。
答案 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中不是很有效。