设为首页 加入收藏

TOP

Python标准库笔记(10) — itertools模块(一)
2018-10-19 16:48:30 】 浏览:57
Tags:Python 标准 笔记 itertools 模块

itertools 用于更高效地创建迭代器的函数工具。

itertools 提供的功能受Clojure,Haskell,APL和SML等函数式编程语言的类似功能的启发。它们的目的是快速有效地使用内存,并且将它们关联在一起以表示更复杂的基于迭代的算法。

基于迭代器的代码比使用列表的代码提供了更好的内存消耗特性。因为直到数据需要使用时才从迭代器中生成,所有数据不需要同时存储在内存中。这种 “惰性” 的处理模式可以减少大型数据集的交换和其他副作用,从而提高性能。

除了 itertools 中定义的函数之外,本文中的示例还使用了一些内置函数进行迭代。

1.合并和分割

chain() 函数将多个迭代器作为参数,并返回一个迭代器,这样它生成所有输入的内容,就像来自于单个迭代器一样。

from itertools import chain

for i in chain([1, 2, 3], ['a', 'b', 'c']):
    print(i, end=' ')

使用 chain() 可以轻松地处理多个序列,而不需要生成一个更大的序列。

# OutPut
1 2 3 a b c 

如果要组合的迭代不是全部预先显式声明的,或者需要惰性计算的,则可以使用 chain.from_iterable() 来替换 chain()

from itertools import chain

def make_iterables_to_chain():
    yield [1, 2, 3]
    yield ['a', 'b', 'c']

for i in chain.from_iterable(make_iterables_to_chain()):
    print(i, end=' ')
# OutPut
1 2 3 a b c 

Python内置函数 zip() 也是返回一个迭代器,但它是将几个迭代器的元素组合成元组。

for i in zip([1, 2, 3], ['a', 'b', 'c']):
    print(i)

zip() 和本模块中的其他函数一样,返回一个可迭代的对象,每次迭代产生一个值。

# OutPut
(1, 'a')
(2, 'b')
(3, 'c')

但是, 使用 zip() 时当第一个输入迭代器耗尽时,zip() 就会停止。如果要处理所有的输入,即使迭代器产生不同数量的值,那么可以使用 zip_longest()

from itertools import zip_longest

r1 = range(3)
r2 = range(2)

print('使用zip会提前结果迭代:')
print(list(zip(r1, r2)))
print()
print('zip_longest会处理完所有值:')
print(list(zip_longest(r1, r2)))

默认情况下,zip_longest() 会使用 None 来填充缺失位置的值。使用 fillvalue 参数来设置不同的替代值。

# OutPut
使用zip会提前结果迭代:
[(0, 0), (1, 1)]

zip_longest会处理完所有值:
[(0, 0), (1, 1), (2, None)]

islice() 函数返回一个迭代器,用于通过索引返回输入迭代器的指定项。

from itertools import islice

print('Stop at 5:')
for i in islice(range(100), 5):
    print(i, end=' ')
print()

print('Start at 5, Stop at 10:')
for i in islice(range(100), 5, 10):
    print(i, end=' ')
print()

print('By tens to 100:')
for i in islice(range(100), 0, 100, 10):
    print(i, end=' ')
print()

islice() 接收和列表切片相同的参数:startstopstepstartstep 参数是可选的。

# OutPut
Stop at 5:
0 1 2 3 4 
Start at 5, Stop at 10:
5 6 7 8 9 
By tens to 100:
0 10 20 30 40 50 60 70 80 90 

tee() 函数作用是根据单个原始输入返回多个独立的迭代器(默认为两个)。

from itertools import islice, tee

r = islice(range(10), 5)
i1, i2 = tee(r)

print('i1:', list(i1))
print('i2:', list(i2))

tee() 具有与Unix tee 实用程序类似的语义,它从它的输入中重复地读取的值并将它们写入一个命名文件和标准输出。 通过 tee() 函数可以将同一组数据提供给多个算法并行处理。

# OutPut
i1: [0, 1, 2, 3, 4]
i2: [0, 1, 2, 3, 4]

需要注意,由 tee() 创建的新迭代器将共享它们的输入,因此在创建新迭代器后不要再使用输入的迭代器。

from itertools import islice, tee

r = islice(range(10), 5)
i1, i2 = tee(r)

print('迭代原始:', end=' ')
for i in r:
    print(i, end=' ')
    if i > 1:
        break
print()

print('i1:', list(i1))
print('i2:', list(i2))

如果原始迭代器已经消耗了一些值,那么新的迭代器将不会生成这些值。

# OutPut
迭代原始: 0 1 2
i1: [3, 4]
i2: [3, 4]

2.计算输入

Python内置的 map() 函数返回一个迭代器。 该迭代器根据输入迭代器中的值调用函数,并返回结果。当任意一个输入迭代器耗尽时它就立刻停止。

def times_two(x):
    return 2 * x

def multiply(x, y):
    return (x, y, x * y)

print('单个输入:')
for i in map(times_two, range(5)):
    print(i, end=' ')

print('\n多个输入:')
r1 = range(5)
r2 = range(5, 10)
for i in map(multiply, r1, r2):
    print('{:d} * {:d} = {:d}'.format(*i))

print('\n迭代停止:')
r1 = range(5)
r2 = range(2)
for i in map(multiply, r1, r2):
    print(i)

在第一个例子中,函数将所有输入值乘以2。在第二个例子中,函数将从两个单独的迭代器中获取的两个参数相乘,并返回一个包含原始参数和计算值的元组。第三个例子中,在生成了两个元组之后便停止了,因为第二个输入已经耗尽。

# OutPut
单个输入:
0 2 4 6 8
多个输入:
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36

迭代停止:
(0, 0, 0)
(1, 1, 1)

starmap() 函数与 map() 类似,但不是从多个迭代器构造元组,而是使用 * 语法将单个迭代器中的项作为参数解包给map函数。

from itertools import starmap

values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]

for i in starmap(lambda x, y: (
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python3练习题系列(02) 下一篇Python 函数的描述

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目