python - 如何在整个迭代中应用函数?
问题描述
我想要f
的工作方式是:
>>> f(chr, [65, 97])
['A', 'a']
>>> f(chr, {65, 97})
{'A', 'a'}
>>> f(chr, {65: 'upper_a', 97: 'lower_a'})
{'A': 'upper_a', 'a': 'lower_a'}
map
很懒,所以我不得不这样做list(map(function, iterable_ds))
,但是这样破坏了原始数据结构。
你怎么能做到这一点?
有一天尝试写作时f
,我得到了这个问题?
每个数据结构类__iter__
都是可迭代的,但就像__next__()
在任何可迭代中给出下一个元素一样,那么什么特殊函数会给 upower 添加任何 xyz 到可迭代 ds?为什么 append 仅用于列表而 add 用于设置?为什么没有像__iter__
and这样的通用接口__next__
?
我试过了
def f(func, i_ds):
ctor = type(i_ds)
holder = list()
for _ in i_ds:
new_val = func(_)
# now what add? append? update? xyz? I hope ctor can consume list
holder.append(new_val)
return ctor(holder) # I know I know it fail for dict type easily
我可以写 f 来处理 dict 但是
- 丑陋
- 如果明天我得到 2 个不同人写的 Tree ds 怎么办
解决方案
映射(dict
类似的东西)与其他集合根本不同,因此您将无法完全避免对它们进行特殊封装,但您至少可以限制所需的专门代码的数量。虽然您是对的,没有通用的“将项目添加到集合”API,但大多数集合都接受构造函数的可迭代值。
使用基于构造函数的ducktyping,对你所拥有的一个小的改进是:
import collections.abc
def f(func, it):
res = map(func, it)
if isinstance(it, collections.abc.Mapping):
# Pair up mapped keys with original values
res = zip(res, it.values())
return type(it)(res)
这不需要任何中间临时数据结构(map
并且zip
是基于惰性生成器的函数;它们仅在最后构造返回类型时才产生值)。它假设所有非Mapping
类型都可以从值的可迭代构造,而所有Mapping
类型都可以从对的可迭代构造;对于通用内置集合(tuple
, list
, set
, frozenset
, dict
),就是这种情况。不太通用的容器不一定能工作(bytes
取决于结果func
,str
如果没有特殊的外壳就不能工作''.join
)。
也就是说,您尝试做的事情是不必要的。您的f
功能正在复制map
,非常糟糕。由于永远不可能编写像您这样具有完美类型复制的函数,因此最好照此执行,map
并将其留给调用者以适当的数据结构重新打包结果(例如,对于dict
s,它们可以显式传递映射函数期望一个键/值tuple
和 pass .items()
,然后dict
从结果中构造;真的,他们可能想要一个dict
理解)。
毕竟,您所要求的永远不会适用于每种输入类型,仅仅是因为构造函数并不总是遵循相同的规则。例如,此代码将无法使用,collections.defaultdict
因为它将default_factory
作为第一个参数,然后是一个可迭代的初始化程序(违反了我们对第一个参数是可迭代初始化程序的期望)。试图处理这意味着更多的特殊情况,而你只是越来越难以确定f
实际做了什么。调用者真的很难明确地做:{myfunc(k): v for k, v in mydict.items()}
而不是f(myfunc, mydict)
,或[myfunc(x) for x in mylist]
/list(map(myfunc, mylist))
结束f(myfunc, mylist)
吗?
推荐阅读
- javascript - 需要帮助在 tfs 2015 中使用 javascript 创建工作项
- reactjs - 从 Firebase 服务器删除一组小时时出错
- php - Symfony 4:注销后显示 flashbag
- sql-server - SQL Server 触发器无法识别插入的行
- r - 通过将列名与 R 中另一个数据框中存在的分组变量匹配来聚合 xts 对象
- javascript - 如何将值从一张纸粘贴到另一张纸到特定列的最后一行
- php - 使用 PHP IMAP 转发电子邮件的简单方法
- ios - 从 PDFDocument iOS 获取页面大小
- python - 素数和元组
- html - 如何在社交媒体上分享您的网站时获得描述,例如不和谐