Skip to main content
 首页 » 编程设计

python之`map` 类函数保留序列类型

2025年05月04日24EasonJim

我想实现一个类似 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 适用于这种情况。

所以我的问题是:

  1. 有没有更好的方法来实现 map2,它支持列表、元组和许多其他格式?
  2. 是否有一种优雅的方式来扩展 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),我可以检查初始化程序的参数”——您是对的!然而,即使您知道初始化器有多少参数,以及它们的名称,您仍然无法获得关于实际应该传递给它们的内容的任何信息。我想你可以编写某种机器学习算法来从文档字符串中找出它......但我认为这远远超出了这个问题的范围(并且它假设作者表现得很好并且首先创建了良好的文档字符串)。