iterutils - itertools 改进

itertools 中充满了使用Python生成器的很好的例子。然而,仍然存在一些关键差距。 iterutils 用功能丰富、经过测试和毕达式的解决方案填补了其中的许多空白。

下面的许多函数有两个版本,一个返回迭代器(由 *_iter 命名模式),以及返回列表的较短的命名便利形式。下面的一些内容是基于iterTools文档中的示例的。

迭代

这些都是发电机,很方便 list -生成包含标准库中不存在的几种常见迭代模式的对应物。

boltons.iterutils.chunked(src, size, count=None, **kw)[源代码]

返回一个列表, count 块,每个块都有 size 元素,从可迭代生成 src 。如果 src 不能被整除 size ,最后一块将少于 size 元素。提供 fill 关键字参数来提供Pad值并启用填充,否则不会进行填充。

>>> chunked(range(10), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
>>> chunked(range(10), 3, fill=None)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, None, None]]
>>> chunked(range(10), 3, count=2)
[[0, 1, 2], [3, 4, 5]]

看见 chunked_iter() 更多信息。

boltons.iterutils.chunked_iter(src, size, **kw)[源代码]

生成 size -大小的块来自 src 可迭代。除非可选的 fill 提供了关键字参数,迭代变量不能被整除 size 将有一个小于 size

>>> list(chunked_iter(range(10), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
>>> list(chunked_iter(range(10), 3, fill=None))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, None, None]]

请注意 fill=None 实际上使用的是 None 作为填充值。

boltons.iterutils.chunk_ranges(input_size, chunk_size, input_offset=0, overlap_size=0, align=False)[源代码]

生成 chunk_size -具有长度的输入的大小区块范围 input_size 。可选地,可以通过以下方式设置输入的开始 input_offset 、块之间的AND和重叠可以通过 overlap_size 。另外,如果 align 设置为 True ,具有以下项的任何项目 i % (chunk_size-overlap_size) == 0 总是在块的开头。

返回(开始、结束)元组的迭代器,每个块一个元组。

>>> list(chunk_ranges(input_offset=10, input_size=10, chunk_size=5))
[(10, 15), (15, 20)]
>>> list(chunk_ranges(input_offset=10, input_size=10, chunk_size=5, overlap_size=1))
[(10, 15), (14, 19), (18, 20)]
>>> list(chunk_ranges(input_offset=10, input_size=10, chunk_size=5, overlap_size=2))
[(10, 15), (13, 18), (16, 20)]
>>> list(chunk_ranges(input_offset=4, input_size=15, chunk_size=5, align=False))
[(4, 9), (9, 14), (14, 19)]
>>> list(chunk_ranges(input_offset=4, input_size=15, chunk_size=5, align=True))
[(4, 5), (5, 10), (10, 15), (15, 19)]
>>> list(chunk_ranges(input_offset=2, input_size=15, chunk_size=5, overlap_size=1, align=False))
[(2, 7), (6, 11), (10, 15), (14, 17)]
>>> list(chunk_ranges(input_offset=2, input_size=15, chunk_size=5, overlap_size=1, align=True))
[(2, 5), (4, 9), (8, 13), (12, 17)]
>>> list(chunk_ranges(input_offset=3, input_size=15, chunk_size=5, overlap_size=1, align=True))
[(3, 5), (4, 9), (8, 13), (12, 17), (16, 18)]
boltons.iterutils.pairwise(src, end=Sentinel('_UNSET'))[源代码]

方便调用的函数 windowed() 在……上面 srcsize 设置为2。

>>> pairwise(range(5))
[(0, 1), (1, 2), (2, 3), (3, 4)]
>>> pairwise([])
[]

除非 end 则对的数量始终比传入的迭代器中的元素数量少一,除非是空输入,这将返回一个空列表。

使用 end 集合,成对的数量等于 src 返回,最后一对的最后一项等于 end

>>> list(pairwise(range(3), end=None))
[(0, 1), (1, 2), (2, None)]

这边请, end 值可以用作发出可迭代结束的信号的哨兵。

boltons.iterutils.pairwise_iter(src, end=Sentinel('_UNSET'))[源代码]

方便调用的函数 windowed_iter() 在……上面 srcsize 设置为2。

>>> list(pairwise_iter(range(5)))
[(0, 1), (1, 2), (2, 3), (3, 4)]
>>> list(pairwise_iter([]))
[]

除非 end 时,对的数量始终比传入的迭代量中的元素数量少一。 src 是空的。

使用 end 集合,成对的数量等于 src 返回,最后一对的最后一项等于 end

>>> list(pairwise_iter(range(3), end=None))
[(0, 1), (1, 2), (2, None)]

这边请, end 值可以用作发出可迭代结束的信号的哨兵。对于无限迭代器,设置 end 没有任何效果。

boltons.iterutils.windowed(src, size, fill=Sentinel('_UNSET'))[源代码]

返回长度正好的元组 size 。如果 fill 是未设置的,且可迭代数太短,无法生成长度窗口 size ,则不返回元组。看见 windowed_iter() 想要更多。

boltons.iterutils.windowed_iter(src, size, fill=Sentinel('_UNSET'))[源代码]

返回长度为的元组 size 表示可迭代上的滑动窗口 src

>>> list(windowed_iter(range(7), 3))
[(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]

如果 fill 是未设置的,且可迭代数太短,无法生成一个长度窗口 size ,则不返回任何窗口元组。

>>> list(windowed_iter(range(3), 5))
[]

使用 fill 设置时,迭代器始终会生成与 src 可迭代。

>>> windowed(range(4), 3, fill=None)
[(0, 1, 2), (1, 2, 3), (2, 3, None), (3, None, None)]

这边请, fill 值对于发出可迭代结束的信号很有用。对于无限迭代器,设置 fill 没有任何效果。

boltons.iterutils.unique(src, key=None)[源代码]

unique() 返回唯一值的列表,该列表由 key ,按照它们第一次出现在可迭代输入中的顺序, src

>>> ones_n_zeros = '11010110001010010101010'
>>> ''.join(unique(ones_n_zeros))
'10'

看见 unique_iter() 有关更多详细信息,请参阅文档。

boltons.iterutils.unique_iter(src, key=None)[源代码]

从可迭代元素中产生唯一元素, src ,基于 key ,按照它们第一次出现的顺序 src

>>> repetitious = [1, 2, 3] * 10
>>> list(unique_iter(repetitious))
[1, 2, 3]

默认情况下, key 是对象本身,但是 key 可以是可调用的属性名称,或者为方便起见,可以是要唯一化为对象的属性的字符串名称,当该属性不存在时依赖于标识。

>>> pleasantries = ['hi', 'hello', 'ok', 'bye', 'yes']
>>> list(unique_iter(pleasantries, key=lambda x: len(x)))
['hi', 'hello', 'bye']
boltons.iterutils.redundant(src, key=None, groups=False)[源代码]

的补语 unique()

默认情况下,将非唯一/重复的值作为 first 中的冗余价值 src 。经过 groups=True 获得按第一个冗余值的位置排序的具有冗余值的所有值的组。这在与某些规格化相结合时很有用 key 功能。

>>> redundant([1, 2, 3, 4])
[]
>>> redundant([1, 2, 3, 2, 3, 3, 4])
[2, 3]
>>> redundant([1, 2, 3, 2, 3, 3, 4], groups=True)
[[2, 2], [3, 3, 3]]

一个使用 key 函数执行不区分大小写的冗余检测。

>>> redundant(['hi', 'Hi', 'HI', 'hello'], key=str.lower)
['Hi']
>>> redundant(['hi', 'Hi', 'HI', 'hello'], groups=True, key=str.lower)
[['hi', 'Hi', 'HI']]

key 中的值时也应使用 src 都不是可控制的。

备注

此函数的此输出用于在需要唯一输入时报告上下文中的重复项。由于是分组返回类型,暂时没有此函数的流等效项。

剥离和拆分

几个 str -受启发的机制在迭代程序上也派上了用场:

boltons.iterutils.split(src, sep=None, maxsplit=None)[源代码]

基于分隔符拆分迭代数。喜欢 str.split() ,但对于所有可迭代的。返回列表列表。

>>> split(['hi', 'hello', None, None, 'sup', None, 'soap', None])
[['hi', 'hello'], ['sup'], ['soap']]

看见 split_iter() 有关更多信息,请参阅文档。

boltons.iterutils.split_iter(src, sep=None, maxsplit=None)[源代码]

基于分隔符拆分迭代数, sep ,最多 maxsplit 次数(默认情况下没有最大值)。 sep 可以是:

  • 单一值

  • 可迭代的分隔符

  • 遇到分隔符时返回True的单参数可调用

split_iter() 生成非分隔符值的列表。分隔符永远不会出现在输出中。

>>> list(split_iter(['hi', 'hello', None, None, 'sup', None, 'soap', None]))
[['hi', 'hello'], ['sup'], ['soap']]

Note that split_iter is based on str.split(), so if sep is None, split() groups separators. If empty lists are desired between two contiguous None values, simply use sep=[None]:

>>> list(split_iter(['hi', 'hello', None, None, 'sup', None]))
[['hi', 'hello'], ['sup']]
>>> list(split_iter(['hi', 'hello', None, None, 'sup', None], sep=[None]))
[['hi', 'hello'], [], ['sup'], []]

使用可调用分隔符:

>>> falsy_sep = lambda x: not x
>>> list(split_iter(['hi', 'hello', None, '', 'sup', False], falsy_sep))
[['hi', 'hello'], [], ['sup'], []]

看见 split() 用于返回列表的版本。

boltons.iterutils.strip(iterable, strip_value=None)[源代码]

从可迭代对象的开始和结束处分条值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.stride的功能。返回一个列表。

>>> strip(['Fu', 'Foo', 'Bar', 'Bam', 'Fu'], 'Fu')
['Foo', 'Bar', 'Bam']
boltons.iterutils.strip_iter(iterable, strip_value=None)[源代码]

从可迭代对象的开始和结束处分条值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.stride的功能。返回一个生成器。

>>> list(strip_iter(['Fu', 'Foo', 'Bar', 'Bam', 'Fu'], 'Fu'))
['Foo', 'Bar', 'Bam']
boltons.iterutils.lstrip(iterable, strip_value=None)[源代码]

从可迭代对象的开头开始剥离值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.ltie的功能。返回一个列表。

>>> lstrip(['Foo', 'Bar', 'Bam'], 'Foo')
['Bar', 'Bam']
boltons.iterutils.lstrip_iter(iterable, strip_value=None)[源代码]

从可迭代对象的开头开始剥离值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.ltie的功能。返回一个生成器。

>>> list(lstrip_iter(['Foo', 'Bar', 'Bam'], 'Foo'))
['Bar', 'Bam']
boltons.iterutils.rstrip(iterable, strip_value=None)[源代码]

从迭代数的末尾剥离值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.rtie的功能。返回一个列表。

>>> rstrip(['Foo', 'Bar', 'Bam'], 'Bam')
['Foo', 'Bar']
boltons.iterutils.rstrip_iter(iterable, strip_value=None)[源代码]

从迭代数的末尾剥离值。已剥离的项目将与参数strie_value的值匹配。功能类似于方法str.rtie的功能。返回一个生成器。

>>> list(rstrip_iter(['Foo', 'Bar', 'Bam'], 'Bam'))
['Foo', 'Bar']

嵌套式

嵌套数据结构很常见。然而,几乎所有的Python紧凑迭代工具都可以处理平面数据:列表理解、映射/过滤器、生成器表达式、迭代工具,甚至其他迭代。

下面的函数使处理嵌套的可迭代程序和其他容器变得与Python本身一样简洁和强大。

boltons.iterutils.remap(root, visit=<function default_visit>, enter=<function default_enter>, exit=<function default_exit>, **kwargs)[源代码]

Remap(“递归映射”)函数用于遍历和转换嵌套结构。列表、元组、集合和字典只是嵌套到异类树状结构中的几个数据结构,这些结构在编程中非常常见。不幸的是,Python内置的操作集合的方法几乎都是平面的。列表理解可能是快速而简洁的,但它们不会递归,这使得对现实世界的数据应用快速更改或复杂转换变得单调乏味。

重新映射达到了列表理解所不能达到的目的。

以下是从一些数据中删除所有None的示例:

>>> from pprint import pprint
>>> reviews = {'Star Trek': {'TNG': 10, 'DS9': 8.5, 'ENT': None},
...            'Babylon 5': 6, 'Dr. Who': None}
>>> pprint(remap(reviews, lambda p, k, v: v is not None))
{'Babylon 5': 6, 'Star Trek': {'DS9': 8.5, 'TNG': 10}}

请注意,尽管字典中嵌套了None,但这两个None都被删除了。对于一句俏皮话来说,这还不错,而这仅仅是个开始。看见 this remap cookbook 寻找更美味的食谱。

Remap有四个主要参数:要遍历的对象和决定如何创建重新映射对象的三个可选可调参数。

参数:
  • root -- 要遍历的目标对象。默认情况下,remap支持可迭代代码,如 listtupledict ,及 set ,但可以遍历的任何对象 enter 会奏效的。

  • visit (callable) -- 中的每一项上都调用此函数 root 。它必须接受三个位置参数, pathkey ,及 valuepath 只是父母密钥的一个元组。 visit 应返回新的键-值对。它也可能会返回 True 作为保持旧项不变的速记,或者 False 若要从新结构中删除该项,请执行以下操作。 visit 在之后调用 enter ,在新家长身上。这个 visit 函数是为根目录中的每个项调用的,包括重复项。对于可遍历的值,在访问完它的所有子对象之后,在新的父对象上调用它。默认的访问行为只是返回未修改的键-值对。

  • enter (callable) -- 此函数用于控制 root 都被遍历了。它接受的参数与 visit :当前项的路径、键和值。它返回一对空白的新父项,以及一个遍历应该访问的项的迭代器。如果 False 而不是迭代器,则不会遍历值。这个 enter 函数在每个唯一值中只调用一次。默认的Enter行为支持映射、序列和集合。不会遍历字符串和所有其他迭代变量。

  • exit (callable) -- 此函数确定访问项目后如何处理这些项目。它获得与其他函数相同的三个参数-- pathkeyvalue --再加上两个:从返回的空白新父对象 enter ,以及由重新映射的新项的列表 visit 。喜欢 enter vt.的. exit 函数在每个唯一值中只调用一次。默认的退出行为是简单地将所有新项添加到新的父项,例如,使用 list.extend()dict.update() 要添加到新父项中的。不可变对象,如 tuplenamedtuple 必须从头开始重新创建,但使用与从 enter 功能。

  • reraise_visit (bool) -- 一种实用的便利 visit 可召回的。当设置为时 False ,remap将忽略由 visit 回拨。导致异常的项目将被保留。有关更多详细信息,请参阅示例。

重新映射旨在涵盖大多数情况,仅包含 visit 可召回的。虽然传入多个可调用函数非常有用,但remap的设计非常简单,因此很少情况下需要传递多个函数。

当经过的时候 enterexit ,在默认行为的基础上构建是常见的,也是最容易的。只需添加 from boltons.iterutils import default_enter (或 default_exit ),并让您的Enter/Exit函数在您的自定义逻辑之前或之后调用默认行为。看见 this example

复制和自参照对象(又称引用循环)在内部被自动处理, as shown here

boltons.iterutils.get_path(root, path, default=Sentinel('_UNSET'))[源代码]

通过表示查找路径的元组从嵌套对象中检索值。

>>> root = {'a': {'b': {'c': [[1], [2], [3]]}}}
>>> get_path(root, ('a', 'b', 'c', 2, 0))
3

路径元组格式故意与 remap() ,但也可以传递单个虚线字符串。

Get_Path的主要目标之一是改进错误消息传递。EAFP很好,但错误消息不是很好。

例如, root['a']['b']['c'][2][1] 回馈 IndexError: list index out of range

什么东西超出了射程?Get_Path当前引发 PathAccessError: could not access 2 from path ('a', 'b', 'c', 2, 1), got error: IndexError('list index out of range',) ,IndexError和KeyError的子类。

如果在任何级别查找失败,也可以传递覆盖整个操作的默认设置。

参数:
  • root -- 支持的词典、列表或其他对象的目标嵌套 __getitem__

  • path (tuple) -- 要在中连续查找的字符串和整数序列 root 。以点分隔的 (a.b )字符串也可以传递。

  • default -- 要返回的值应为 PathAccessError 可以提出例外情况。

boltons.iterutils.research(root, query=<function <lambda>>, reraise=False)[源代码]

这个 research() 函数用法 remap() 中嵌套的任何数据进行递归 root 属性指定的给定条件匹配的值。 query 可召回的。

结果以列表的形式返回 (path, value) 成对的。路径是与接受的格式相同的元组 get_path() 。这对于比较嵌套在两个或多个不同结构中的值很有用。

下面是一个查找所有整数的简单示例:

>>> root = {'a': {'b': 1, 'c': (2, 'd', 3)}, 'e': None}
>>> res = research(root, query=lambda p, k, v: isinstance(v, int))
>>> print(sorted(res))
[(('a', 'b'), 1), (('a', 'c', 0), 2), (('a', 'c', 2), 3)]

请注意如何 query 遵循着同样的,熟悉的 path, key, value 签名为 visitenter 功能启用 remap() ,并返回一个 bool

参数:
  • root -- 要搜索的目标对象。支持与相同类型的对象 remap() ,包括 listtupledict ,及 set

  • query (callable) -- 该函数调用每个对象以确定是否将其包括在搜索结果中。Callable必须接受三个参数, pathkey ,及 value ,通常缩写为 pk ,及 v ,与 entervisit 从… remap()

  • reraise (bool) -- 是否重新激活由 query 或者简单地删除导致错误的结果。

使用 research() 检查数据结构的细节很容易,比如查找某个深度的值(使用 len(p) )以及更多。如果需要更高级的功能,请签出代码并制作自己的代码 remap() 包装器,并考虑 submitting a patch 好了!

boltons.iterutils.flatten(iterable)[源代码]

flatten() 返回来自的所有元素的折叠列表 iterable 同时折叠任何嵌套的可迭代对象。

>>> nested = [[1, 2], [[3], [4, 5]]]
>>> flatten(nested)
[1, 2, 3, 4, 5]
boltons.iterutils.flatten_iter(iterable)[源代码]

flatten_iter() 生成来自的所有元素 iterable 同时折叠任何嵌套的可迭代对象。

>>> nested = [[1, 2], [[3], [4, 5]]]
>>> list(flatten_iter(nested))
[1, 2, 3, 4, 5]

数字

数字序列是Python迭代的明显目标,比如内置的 range() ,以及 itertools.count() 。就像 迭代 上面的成员返回迭代器和列表,但接受数值输入而不是迭代量。

boltons.iterutils.backoff(start, stop, count=None, factor=2.0, jitter=False)[源代码]

返回按几何方式递增的浮点数的列表,适合与 exponential backoff 。一模一样 backoff_iter() ,但没有 'repeat' 选项 count 。看见 backoff_iter() 了解更多详细信息。

>>> backoff(1, 10)
[1.0, 2.0, 4.0, 8.0, 10.0]
boltons.iterutils.backoff_iter(start, stop, count=None, factor=2.0, jitter=False)[源代码]

生成一个几何递增的浮点数序列,适合与 exponential backoff 。以.开始 start ,增加了 factor 直到 stop ,则可以选择停止迭代一次。 count 数字是产生的。 factor 通常,使用正确配置的退避重试会为更大的服务生态系统创建行为更好的组件。

>>> list(backoff_iter(1.0, 10.0, count=5))
[1.0, 2.0, 4.0, 8.0, 10.0]
>>> list(backoff_iter(1.0, 10.0, count=8))
[1.0, 2.0, 4.0, 8.0, 10.0, 10.0, 10.0, 10.0]
>>> list(backoff_iter(0.25, 100.0, factor=10))
[0.25, 2.5, 25.0, 100.0]

一个简化的用法示例:

for timeout in backoff_iter(0.25, 5.0):
    try:
        res = network_call()
        break
    except Exception as e:
        log(e)
        time.sleep(timeout)

对大型系统的增强将是增加变化,或者 jitter ,设置为超时值。这样做是为了避免网络呼叫接收端的一群人发出雷鸣般的声音。

最后,为了 count ,特殊的价值 'repeat' 可以无限期地继续屈服。

参数:
  • start (float) -- 基线为正数。

  • stop (float) -- 正数表示最大值。

  • count (int) -- 停止迭代前的步骤数。缺省值为 startstop 。传递字符串, 'repeat' ,以无限期地继续迭代。

  • factor (float) -- 指数级增长的速度。默认为 2.0 ,例如, [1, 2, 4, 8, 16]

  • jitter (float) -- 一个介于两者之间的因素 -1.01.0 ,用于统一随机化,从而在分布式系统中分散超时,从而避免节奏影响。正值使用基本回退曲线作为最大值,负值使用曲线作为最小值。设置为1.0或 True 获得接近以太网久经考验的退避解决方案的抖动。默认为 False

boltons.iterutils.frange(stop, start=None, step=1.0)[源代码]

A range() 克隆基于浮点数的范围。

>>> frange(5)
[0.0, 1.0, 2.0, 3.0, 4.0]
>>> frange(6, step=1.25)
[0.0, 1.25, 2.5, 3.75, 5.0]
>>> frange(100.5, 101.5, 0.25)
[100.5, 100.75, 101.0, 101.25]
>>> frange(5, 0)
[]
>>> frange(5, 0, step=-1.25)
[5.0, 3.75, 2.5, 1.25]
boltons.iterutils.xfrange(stop, start=None, step=1.0)[源代码]

相同于 frange() ,但基于生成器,而不是返回列表。

>>> tuple(xfrange(1, 3, step=0.75))
(1.0, 1.75, 2.5)

看见 frange() 了解更多详细信息。

分类

这些函数对可迭代对象进行操作,根据给定的条件将其分组。

boltons.iterutils.bucketize(src, key=<class 'bool'>, value_transform=None, key_filter=None)[源代码]

中的组值 src 返回的值可迭代 key

>>> bucketize(range(5))
{False: [0], True: [1, 2, 3, 4]}
>>> is_odd = lambda x: x % 2 == 1
>>> bucketize(range(5), is_odd)
{False: [0, 2, 4], True: [1, 3]}

keybool 默认情况下,它可以是可调用的,也可以是字符串或列表(如果它是字符串),它是要对对象进行分段化的属性的名称。

>>> bucketize([1+1j, 2+2j, 1, 2], key='real')
{1.0: [(1+1j), 1], 2.0: [(2+2j), 2]}

如果 key 是一个列表,它包含放置每个对象的存储桶

>>> bucketize([1,2,365,4,98],key=[0,1,2,0,2])
{0: [1, 4], 1: [2], 2: [365, 98]}

值列表未进行重复数据消除:

>>> bucketize([None, None, None, 'hello'])
{False: [None, None, None], True: ['hello']}

分成3组以上

>>> bucketize(range(10), lambda x: x % 3)
{0: [0, 3, 6, 9], 1: [1, 4, 7], 2: [2, 5, 8]}

bucketize 有几个高级选项在某些情况下很有用。 value_transform 可用于在将值添加到存储桶时修改值,以及 key_filter 将允许将某些存储桶排除在收集之外。

>>> bucketize(range(5), value_transform=lambda x: x*x)
{False: [0], True: [1, 4, 9, 16]}
>>> bucketize(range(10), key=lambda x: x % 3, key_filter=lambda k: k % 3 != 1)
{0: [0, 3, 6, 9], 2: [2, 5, 8]}

注意在这些例子中的一些例子中最多有两个键, TrueFalse ,并且存在的每个密钥都具有至少一个条目的列表。看见 partition() 用于专门用于二进制用例的版本。

boltons.iterutils.partition(src, key=<class 'bool'>)[源代码]

与以下内容无关 str.partition()partition 就像 bucketize() ,但为了更方便起见,返回 (truthy_values, falsy_values)

>>> nonempty, empty = partition(['', '', 'hi', '', 'bye'])
>>> nonempty
['hi', 'bye']

key 默认为 bool ,但可以小心地重写,以使用返回以下两个函数之一的函数 TrueFalse 或要对其进行对象分区的属性的字符串名称。

>>> import string
>>> is_digit = lambda x: x in string.digits
>>> decimal_digits, hexletters = partition(string.hexdigits, is_digit)
>>> ''.join(decimal_digits), ''.join(hexletters)
('0123456789', 'abcdefABCDEF')

分选

内置的 sorted() 很棒,但是当您想要部分覆盖排序顺序时该怎么办呢?

boltons.iterutils.soft_sorted(iterable, first=None, last=None, key=None, reverse=False)[源代码]

当你关心某些元素的顺序,而不是其他元素的顺序时。

使用此选项可以按特定顺序浮动到顶部和/或底部,同时按照正常顺序对其余元素进行排序 sorted() 规矩。

>>> soft_sorted(['two', 'b', 'one', 'a'], first=['one', 'two'])
['one', 'two', 'a', 'b']
>>> soft_sorted(range(7), first=[6, 15], last=[2, 4], reverse=True)
[6, 5, 3, 1, 0, 2, 4]
>>> import string
>>> ''.join(soft_sorted(string.hexdigits, first='za1', last='b', key=str.lower))
'aA1023456789cCdDeEfFbB'
参数:
  • iterable (list) -- 列表或其他可迭代排序的列表。

  • first (list) -- 对应该出现在返回列表开头的元素强制执行的序列。

  • last (list) -- 对应出现在返回列表末尾的元素强制执行的序列。

  • key (callable) -- Callable用于为每个要排序的项生成一个类似的键,与 sorted() 。请注意,中的条目 firstlast 应该是这些物品的钥匙。默认为通过/身份功能。

  • reverse (bool) -- 无论元素是否未显式排序 firstlast 是否应该按相反的顺序排列。

按排序顺序返回新列表。

boltons.iterutils.untyped_sorted(iterable, key=None, reverse=False)[源代码]

一个版本的 sorted() 这将愉快地对异类类型的可迭代进行排序,并返回一个新的列表,类似于遗留的Python的行为。

>>> untyped_sorted(['abc', 2.0, 1, 2, 'def'])
[1, 2.0, 2, 'abc', 'def']

请注意,相互可排序的类型如何按预期进行排序,就像上面的整数和浮点数的情况一样。

备注

不同版本和构建版本的结果可能会有所不同,但该函数将生成一个排序列表,但对于显式不可排序的对象除外。

减少

reduce() 是一个强大的功能,但它也是非常开放的,并不总是最具可读性的。标准库认识到这一点,添加了 sum()all() ,及 any() 。所有这些函数都需要一个基本运算符 (+and ,及 or ),并使用运算符将可迭代变量转换为单个值。

此类别中的函数遵循相同的精神,将列表之类的可迭代函数转换为单个值:

boltons.iterutils.one(src, default=None, key=None)[源代码]

沿着与内置建筑相同的路线, all()any() ,并且类似于 first()one() 返回给定迭代数中的单个对象 src 它的计算结果为 True ,由Callable确定 key 。如果取消设置, key 默认为 bool 。如果没有找到这样的对象, default 是返回的。如果 default 没有通过, None 是返回的。

如果 src 具有多个计算结果为 True ,或者如果没有满足该条件的对象,则返回 default 。这就像是一个 XOR 在可迭代数上。

>>> one((True, False, False))
True
>>> one((True, False, True))
>>> one((0, 0, 'a'))
'a'
>>> one((0, False, None))
>>> one((True, True), default=False)
False
>>> bool(one(('', 1)))
True
>>> one((10, 20, 30, 42), key=lambda i: i > 40)
42

看见 Martín Gaitán's original repo 以获取更多用例。

boltons.iterutils.first(iterable, default=None, key=None)[源代码]

返回的第一个元素 iterable 它的计算结果为 True ,否则返回 None 或可选 default 。类似于 one()

>>> first([0, False, None, [], (), 42])
42
>>> first([0, False, None, [], ()]) is None
True
>>> first([0, False, None, [], ()], default='ohai')
'ohai'
>>> import re
>>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)'])
>>> m.group(1)
'bc'

可选的 key 参数指定一个单参数谓词函数,类似于 filter() 。这个 key 参数(如果提供)应为关键字形式。例如,查找可迭代中的第一个偶数:

>>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
4

由Hynek Schlawack贡献,《 the original standalone module

boltons.iterutils.same(iterable, ref=Sentinel('_UNSET'))[源代码]

same() 退货 True 当中的所有值 iterable 彼此相等,或者可选地为参考值, ref 。类似于 all()any() 因为它计算一个可迭代数并返回一个 boolsame() 退货 True 用于空的可迭代对象。

>>> same([])
True
>>> same([1])
True
>>> same(['a', 'a', 'a'])
True
>>> same(range(20))
False
>>> same([[], []])
True
>>> same([[], []], ref='test')
False

类型检查

按照与特征检查内置相同的脉络, callable()

boltons.iterutils.is_iterable(obj)[源代码]

在性质上与 callable()is_iterable 退货 True 如果对象是 iterableFalse 如果不是的话。

>>> is_iterable([])
True
>>> is_iterable(object())
False
boltons.iterutils.is_scalar(obj)[源代码]

一个近乎镜像的 is_iterable() 。退货 False 如果对象是可迭代容器类型。字符串也被视为标量,因为字符串更多地被视为整数值,而不是1字符子字符串的可迭代。

>>> is_scalar(object())
True
>>> is_scalar(range(10))
False
>>> is_scalar('hello')
True
boltons.iterutils.is_collection(obj)[源代码]

的对立面 is_scalar() 。退货 True 如果对象是可迭代对象而不是字符串。

>>> is_collection(object())
False
>>> is_collection(range(10))
True
>>> is_collection('hello')
False