我想实现一个类似 map 的函数,它保留输入序列的类型。 map 不保留它:
map(str, (8, 9)) # input is a tuple
=> ['8', '9'] # output is a list
我想到的一种方法是这样的:
def map2(f, seq):
return type(seq)( f(x) for x in seq )
map2(str, (1,2))
=> ('1', '2')
map2(str, [3,4])
=> ['3', '4']
map2(str, deque([5,6]))
=> deque(['5', '6'])
但是,如果 seq 是迭代器/生成器,这将不起作用。 imap 适用于这种情况。
所以我的问题是:
- 有没有更好的方法来实现
map2,它支持列表、元组和许多其他格式? - 是否有一种优雅的方式来扩展
map2以支持生成器(就像imap一样)?显然,我想避免:try: return map2(...) except TypeError: return imap(...)
我正在寻找类似的东西的原因是我正在编写一个函数装饰器,它将返回值从类型 X 转换为 Y。如果原始函数返回一个序列(假设一个序列只能是列表、元组或生成器),我假设它是 X 的序列,我想将它转换为相应的 Y 序列(同时保留序列的类型)。
您可能已经意识到,我使用的是 python 2.7,但 python 3 也很有趣。
请您参考如下方法:
您的形式主义也不适用于 map(str,'12')。
最终,您不知道可迭代对象的类型实际上会在构造函数/初始化程序中接受哪些参数,因此通常无法做到这一点。另请注意,imap 不会为您提供与生成器相同的类型:
>>> type(x for x in range(10))
<type 'generator'>
>>> type(imap(str,range(10)))
<type 'itertools.imap'>
>>> isinstance((x for x in range(10)),type(imap(str,range(10))))
False
您可能会想“通过 Python 的自省(introspection),我可以检查初始化程序的参数”——您是对的!然而,即使您知道初始化器有多少参数,以及它们的名称,您仍然无法获得关于实际应该传递给它们的内容的任何信息。我想你可以编写某种机器学习算法来从文档字符串中找出它......但我认为这远远超出了这个问题的范围(并且它假设作者表现得很好并且首先创建了良好的文档字符串)。
