`map`-like函数保留序列类型

shx*_*hx2 1 python list generator python-2.7

我想实现一个类似map的函数,它保留输入序列的类型. map不保留它:

map(str, (8, 9))  # input is a tuple
=> ['8', '9']     # output is a list
Run Code Online (Sandbox Code Playgroud)

我提出的一种方法是:

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'])
Run Code Online (Sandbox Code Playgroud)

但是,如果seq是迭代器/生成器,则不起作用. imap适用于这种情况.

所以我的问题是:

  1. 有没有更好的实现方式map2,支持列表,元组和其他许多方法?
  2. 是否有一种优雅的方式可以扩展map2到也支持生成器(就像imap这样)?显然,我想避免:try: return map2(...) except TypeError: return imap(...)

我正在寻找类似的东西的原因是我正在编写一个函数装饰器,它将返回值从X型转换为Y.如果原始函数返回一个序列(让我们假设一个序列只能是一个列表,我认为它是一个X序列,我想把它转换成Y的相应序列(同时保留序列的类型).

你可能已经意识到,我正在使用python 2.7,但python 3也很有用.

mgi*_*son 7

你的形式主义也不起作用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
Run Code Online (Sandbox Code Playgroud)

你可能会想到自己"肯定有python的内省,我可以检查初始化器的参数" - 你是对的!但是,即使您知道初始化程序有多少参数以及它们的名称,您仍然无法获得有关您实际应该传递给它们的信息.我想你可以编写某种机器学习算法来从文档字符串中找出它...但我认为这远远超出了这个问题的范围(并且它假设作者表现得很好并且开始创建好的文档字符串).

  • @ shx2 - 我认为可能没有*easy*方法来做这个,因为在python中我们喜欢鸭子打字.只要你烤的时候它的味道就像鸭子一样,你有什么类型并不重要.**调用者**可以将它转换为不同的类型,当它们对它们有趣时. (3认同)