Sli*_*Jim 2 python python-itertools
这个
from __future__ import print_function
from functools import partial
from itertools import imap, product
identity = lambda x: x
identity.__repr__ = 'id'
map_identity = partial(map, identity)
map_identity.__repr__ = 'map'
imap_identity = partial(imap, identity)
imap_identity.__repr__ = 'imap'
prod_map = partial(product, repeat=1)
prod_map.__repr__ = 'prod'
list(map(
lambda (f, g):
print(
"{f_repr:4}(range(10)) compare {g_repr:4}(range(10)): "\
"{{ less: {less:1}, equal: {equal:1}}}".format(
f_repr=f.__repr__,
g_repr=g.__repr__,
less=f(range(16))<g(range(16)),
equal=f(range(16))==g(range(16)),
)
),
product([identity, map_identity, imap_identity, prod_map], repeat=2)
))
Run Code Online (Sandbox Code Playgroud)
回报
id (range(10)) compare id (range(10)): { less: 0, equal: 1}
id (range(10)) compare map (range(10)): { less: 0, equal: 1}
id (range(10)) compare imap(range(10)): { less: 0, equal: 0}
id (range(10)) compare prod(range(10)): { less: 0, equal: 0}
map (range(10)) compare id (range(10)): { less: 0, equal: 1}
map (range(10)) compare map (range(10)): { less: 0, equal: 1}
map (range(10)) compare imap(range(10)): { less: 0, equal: 0}
map (range(10)) compare prod(range(10)): { less: 0, equal: 0}
imap(range(10)) compare id (range(10)): { less: 1, equal: 0}
imap(range(10)) compare map (range(10)): { less: 1, equal: 0}
imap(range(10)) compare imap(range(10)): { less: 1, equal: 0}
imap(range(10)) compare prod(range(10)): { less: 1, equal: 0}
prod(range(10)) compare id (range(10)): { less: 1, equal: 0}
prod(range(10)) compare map (range(10)): { less: 1, equal: 0}
prod(range(10)) compare imap(range(10)): { less: 0, equal: 0}
prod(range(10)) compare prod(range(10)): { less: 1, equal: 0}
Run Code Online (Sandbox Code Playgroud)
迭代器的原因是什么,imap并且在比较时与prod_map列表id/ 行为不同map?
这里有几个不同的问题.
首先,map2.x 的结果不是迭代器而是列表.通过按字典顺序比较两个列表来比较它们的元素.
迭代器和许多其他迭代也是如此(因为这样做会消耗迭代器,使它们变得无用).因此,像Python中的大多数类型一样,没有任何其他明显的方法来比较它们的相等性,大多数迭代器类型(包括生成器,以及特殊的C实现的迭代器itertools)都比较id.碰巧迭代相同序列的两个不同的迭代器通常不会相等.
当然,identity如果您将列表传递给它,结果也是一个列表.并且range(16)是一个列表.因此,在两个函数都在的情况下(id, map),结果是相等的; 在任何一个函数进入的情况下(imap, prod),结果将不相等.
其次,<对两个不相关类型的值使用(或其他排序比较)可以为您提供一致的任何运行但任意顺序.问一个人为什么不是另一个人是没有意义的.它必须是一个或另一个; 它无关紧要.(如果你真的想知道细节,你可以阅读你选择的解释器的源代码.CPython的实现就像你想象的那样简单,愚蠢:不相关类型的值有效地按其类型的规范名称排序. )
那么,如果你想知道两个迭代器是否迭代相同的序列呢?
一般来说,你不能.例如,chain(0, count(1))并count(0)清楚地迭代相同的序列...但它会花费你无限的时间来计算出来.(当然在这种情况下,如果有足够的信息,如何chain,count工作和访问他们的内部,你可以在有限的时间内完成 - 至少我希望如此,或者你仍然在段落的早期验证"清楚"位.但是,如果不解决暂停问题,你无法做到这一点.)
在简单的情况下,您可以只调用list每个,比较两个列表(然后使用列表而不是原始的,现在为空的迭代器).在某些情况下(例如,你可以依赖它们 - 非常早 - 或相等 - 但很小,但你不能依赖它们,如果不同,那么你可以使用tee并且只能迭代到第一个区别(然后使用teed副本而不是原始迭代器),但这基本上是相同的想法.
但实际上,你可能想要的只是这样:
equal_values = (x1 == x2 for x1, x2 in izip(i1, i2))
Run Code Online (Sandbox Code Playgroud)
然后你有与任何其他迭代器完全相同的问题,你已经知道如何处理,对吧?例如,如果您确定它们不是无限的,并且您愿意使用迭代器来查明它们是否相等:
equal_sequences = all(equal_values)
Run Code Online (Sandbox Code Playgroud)
Python 3.x几乎消除了第一个问题,它阻止你无缘无故地构建大量的中间列表,而是鼓励你将事物保存在迭代器中,直到你需要迭代它们(通常一次,最后).特别是,range不返回list- 尽管它返回的东西比较等于自身 - 并map返回迭代器.所以,只有当这两个功能id都能让你获得平等时.
Python 3.x完全消除了第二个问题,只是不让你比较不相关类型的值.TypeError如果你试试,你会得到一个.所以,你不能误导寻找一个值小于另一个值的不存在的原因.
| 归档时间: |
|
| 查看次数: |
2243 次 |
| 最近记录: |