itertools:用于处理可迭代对象的模块

简介: itertools:用于处理可迭代对象的模块

Python 有一个内置模块 itertools,从名字可以看出它是专门用来处理可迭代对象的,那么它都支持哪些操作呢?一起来看一下吧。

itertools.chain

接收多个可迭代对象(或者迭代器)作为参数,返回一个迭代器。它会生成所有输入迭代器的元素,就好像这些元素来自一个迭代器一样。

import itertools
c = itertools.chain([1, 2, 3], "abc", {"k1": "v1", "k2": "v2"})
# 直接打印的话是一个对象
print(c) 
"""
<itertools.chain object at 0x00000000029745F8>
"""
print(list(c)) 
"""
1 2 3 a b c k1 k2
"""
# 还可以使用 chain.from_iterable
# 参数接收多个可迭代对象组成的一个可迭代对象
c = itertools.chain.from_iterable(
    [[1, 2, 3], "abc", {"k1": "v1", "k2": "v2"}]
)
print(list(c)) 
"""
1 2 3 a b c k1 k2
"""


itertools.zip_longest

从名字上可以看出,功能和内置的 zip 类似。确实如此,就是将多个可迭代对象对应位置的元素组合起来,像拉链(zip)一样。只不过内置的 zip 是 "木桶原理",一方匹配到头了,那么就不匹配了,而 zip_longest 是以长的那一方为基准。

import itertools
# 内置的 zip 是把多个迭代器对象中的每一个元素按照顺序组合到一个元组中
name = ["高老师", "猪哥", "S 佬"]
where = ["江苏", "北京", "深圳"]
z = zip(name, where)
print(z)
"""
<zip object at 0x00000257F3FEBEC0>
"""
print(list(z))
"""
[('高老师', '江苏'), ('猪哥', '北京'), ('S 佬', '深圳')]
"""
# 但如果两者长度不一致怎么办?
name = ["高老师", "猪哥", "S 佬", "xxx"]
where = ["江苏", "北京", "深圳"]
print(list(zip(name, where)))
"""
[('高老师', '江苏'), ('猪哥', '北京'), ('S 佬', '深圳')]
"""
# 可以看到,长度不一致的时候,当一方结束之后就停止匹配
# 如果想匹配长的,那么可以使用 itertools 下面的 zip_longest
print(list(itertools.zip_longest(name, where))) 
"""
[('高老师', '江苏'), ('猪哥', '北京'), ('S 佬', '深圳'), ('xxx', None)]
"""
# 默认使用 None 进行匹配,当然我们也可以指定内容
print(list(itertools.zip_longest(name, where, fillvalue="中国")))
"""
[('高老师', '江苏'), ('猪哥', '北京'), ('S 佬', '深圳'), ('xxx', '中国')]
"""


itertools.islice

如果一个迭代器里面包含了很多元素,我们只想一部分的话,可以使用 islice,按照索引从迭代器中返回所选择的元素,并且得到的还是一个迭代器。

import itertools
num = range(20)
# 选择 index=5 到 index=10(不包含)的位置
s = itertools.islice(num, 5, 10)
print(list(s))  # [5, 6, 7, 8, 9]
# 选择开头到 index=5 的位置
s = itertools.islice(num, 5)
print(list(s))  # [0, 1, 2, 3, 4]
# 选择从 index=5 到 index=15(不包含)的位置,步长为 3
s = itertools.islice(num, 5, 15, 3)
print(list(s))  # [5, 8, 11, 14]

注意:islice 不支持负数索引,因为不知道迭代器有多长,除非全部读取,可是那样的话干嘛不直接转为列表之后再用切片获取呢?

之所以使用 islice 这种形式,就是为了在不全部读取的情况下,也能选择出我们想要的部分,所以这种方式只支持从前往后,不能从后往前。

itertools.tee

将一个可迭代对象拷贝 n 份。

import itertools
r = [1, 2, 3, 4, 5]
i1, i2 = itertools.tee(r, 2)
print(list(i1))  # [1, 2, 3, 4, 5]
print(list(i2))  # [1, 2, 3, 4, 5]


itertools.count

import itertools
"""
count(start=0, step=1) 返回一个迭代器,负责无限地生成连续的整数
接收两个参数:起始(默认为0)和步长(默认为1)
等价于:
def count(firstval=0, step=1):
    x = firstval
    while 1:
        yield x
        x += step
"""
# 起始值为 5,步长为 2
c1 = itertools.count(5, 2)
print(list(itertools.islice(c1, 5))) 
"""
[5, 7, 9, 11, 13]
"""


itertools.cycle

import itertools
"""
cycle(iterable) 返回一个迭代器,会无限重复里面的内容,直到内存耗尽
"""
c2 = itertools.cycle("abc")
print(list(itertools.islice(c2, 10)))
"""
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a']
"""


itertools.repeat

import itertools
"""
repeat(obj, times=None),无限重复 obj,除非指定 times
"""
# 重复指定的次数
print(list(itertools.repeat("abc", 3))) 
"""
['abc', 'abc', 'abc']
"""


itertools.dropwhile

删除满足条件的值,注意:是删除。

import itertools
l = [1, 2, 3, 4, 5]
drop_l = itertools.dropwhile(lambda x: x < 3, l)
# 依旧返回迭代器
print(drop_l) 
"""
<itertools.dropwhile object at 0x000001AD63AD0488>
"""
# 可以看到小于3的都被丢掉了
print(list(drop_l))  
"""
[3, 4, 5]
"""


itertools.takewhile

这个和 filter 是一样的,保留满足条件的值。

import itertools
l = [1, 2, 3, 4, 5]
take_l = itertools.takewhile(lambda x: x < 3, l)
print(take_l) 
"""
<itertools.takewhile object at 0x000001D37F512948>
"""
print(list(take_l)) 
"""
[1, 2]
"""
filter_l = filter(lambda x: x < 3, l)
print(list(filter_l))  
"""
[1, 2]
"""


itertools.compress

提供了另一种过滤可迭代对象元素的方法。

import itertools
condition = [True, False, True, True, False]
data = [1, 2, 3, 4, 5]
print(list(itertools.compress(data, condition))) 
"""
[1, 3, 4]
"""
# 除了指定 True 和 False,还可以使用 Python 其它类型的值
# 会以其对应的布尔值作为判断依据
condition = [1, 0, "x", "x", {}]  
print(list(itertools.compress(data, condition))) 
"""
[1, 3, 4]
"""


itertools.accumulate

accumulate 处理输入的序列,得到一个类似于斐波那契的结果。

import itertools
print(list(itertools.accumulate(range(5))))  
"""
[0, 1, 3, 6, 10]
"""
print(list(itertools.accumulate("abcde")))  
"""
["a", "ab", "abc", "abcd", "abcde"]
"""
# 所以这里的相加还要看具体的含义
try:
    print(list(itertools.accumulate([[1, 2], (3, 4)])))
except TypeError as e:
    print(e)  
    """
    can only concatenate list (not "tuple") to list
    """
    # 这里就显示无法将列表和元组相加
# 当然也可以自定义
data = [1, 2, 3, 4, 5]
method = lambda x, y: x * y
print(list(itertools.accumulate(data, method))) 
"""
[1, 2, 6, 24, 120]
"""
# 可以看到这里的结果就改变了


itertools.product

product 则是会将多个可迭代对象组合成一个笛卡尔积。

import itertools
print(list(itertools.product([1, 2, 3], [2, 3]))) 
"""
[(1, 2), (1, 3), (2, 2), (2, 3), (3, 2), (3, 3)]
"""


itertools.permutations

import itertools
data = [1, 2, 3, 4]
print(list(itertools.permutations(data)))
# 根据排列组合,显然是 A44,总共 4 * 3 * 2 * 1 = 24 种组合
"""
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2),
(2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1),
(3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1),
(4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
"""
# 结果是 A42,总共 4 * 3 = 12 种组合
print(list(itertools.permutations(data, 2)))
"""
[(1, 2), (1, 3), (1, 4), 
 (2, 1), (2, 3), (2, 4), 
 (3, 1), (3, 2), (3, 4), 
 (4, 1), (4, 2), (4, 3)]
"""


itertools.combinations

permutations 显然是考虑了顺序,相当于排列组合里面 A,而 combinations 只考虑元素是否一致,而不管顺序,相当于排列组合里面的 C。

import itertools
# permutations 只要顺序不同就看做一种结果
# combinations 则保证只要元素相同就是同一种结果
data = "abcd"
print(list(itertools.combinations(data, 3)))  
"""
[('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd')]
"""
# 如果拿抽小球来作比喻的话,显然 combinations 是不放回的,也就是不会重复单个的输入元素
# 但有时候可能也需要考虑包含重复元素的组合,相当于抽小球的时候有放回
# 对于这种情况,可以使用 combinations_with_replacement
print(list(itertools.combinations_with_replacement(data, 3)))
"""
[('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'a', 'd'), ('a', 'b', 'b'),
('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'c'), ('a', 'c', 'd'), ('a', 'd', 'd'),
('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'b', 'd'), ('b', 'c', 'c'), ('b', 'c', 'd'),
('b', 'd', 'd'), ('c', 'c', 'c'), ('c', 'c', 'd'), ('c', 'd', 'd'), ('d', 'd', 'd')]
"""


以上就是该模块的用法,但说实话,感觉大部分都没啥卵用。

相关文章
|
6月前
|
机器学习/深度学习 C语言 索引
数组计算模块NumPy(一)
NumPy是Python科学计算的核心库,提供高性能的数组和矩阵操作,支持大量数学函数。它包括一维、二维到多维数组,并通过C实现,优化了计算速度。
数组计算模块NumPy(一)
|
6月前
|
索引 Python
数组计算模块NumPy(二)
NumPy教程概要:介绍数组切片、二维数组索引、重塑、转置和数组操作。讨论了切片语法`[start:stop:step]`,二维数组的索引方式,以及reshape方法改变数组形状。涉及转置通过`.T`属性或`transpose()`函数实现,数组增加使用`hstack()`和`vstack()`,删除用`delete()`。还提到了矩阵运算,包括加减乘除,并展示了`numpy.dot()`和`@`运算符的使用。最后提到了排序函数`sort()`、`argsort()`和`lexsort()`,以及NumPy的统计分析函数如均值、标准差等。
|
7月前
|
索引 Python
NumPy 数组迭代与合并详解
NumPy 数组迭代包括基本和高级方法。使用 `for` 循环可迭代一维、二维及多维数组。`np.nditer()` 提供更多控制,如迭代顺序、过滤、类型转换和步长。`np.ndenumerate()` 返回元素及其索引。练习涉及合并数组操作。
60 0
|
7月前
|
数据库 索引 Python
Python中collections模块的namedtuple具名元组:原理、应用与优势
在Python的`collections`模块中,`namedtuple`是一个用于创建具有名称属性的元组的工厂函数。它提供了一种更直观、更易于理解的方式来组织和访问数据。通过`namedtuple`,我们可以为元组的每个位置指定一个名字,从而使元组更加有意义和易于操作。本文将深入解析`namedtuple`的原理、使用方法以及它在实际应用中的优势。
|
7月前
|
运维 Shell Sentinel
第八章 Python可迭代对象、迭代器和生成器
第八章 Python可迭代对象、迭代器和生成器
|
7月前
|
Python
Python中使用for循环列表或可迭代对象
Python中使用for循环列表或可迭代对象
63 0
|
存储 C语言 Python
Python|认识可迭代对象与迭代器
Python|认识可迭代对象与迭代器
88 1
|
存储 Python 容器
理解 Python 迭代对象、迭代器、生成器
理解 Python 迭代对象、迭代器、生成器
151 0
|
Python 容器
【Python零基础入门篇 · 20】:可迭代对象和迭代器的转换、自定义迭代器类、异常类、生成器
【Python零基础入门篇 · 20】:可迭代对象和迭代器的转换、自定义迭代器类、异常类、生成器
147 0
【Python零基础入门篇 · 20】:可迭代对象和迭代器的转换、自定义迭代器类、异常类、生成器

热门文章

最新文章