Python数据大杀器:掌握collections与heapq,编写更高效的算法与数据处理

前言

在计算机科学的世界中,数据结构是构建强大和高效算法的基石。Python作为一门广泛应用的编程语言,以其丰富的数据结构模块为程序员提供了强大的工具。本文旨在深入研究Python的collectionsheapq模块,通过更丰富的示例和详细的解释,让读者对这两个模块的使用和原理有更深刻的理解。

文章目录

      • 前言
      • 一. `collections`模块:数据结构的瑞士军刀
      • 1.1 `deque`:双端队列
        • 1.1.1 操作示例:插入、删除、迭代
        • 1.1.2 高效性能:与列表比较
        • 1.1.3 应用场景:广度优先搜索(BFS)等
      • 1.2 `Counter`:计数器
        • 1.2.1 统计频率:文本处理、数据分析
        • 1.2.2 更新计数器:可迭代对象的应用
        • 1.2.3 实用技巧:找出最常见的元素
      • 1.3 `OrderedDict`:有序字典
        • 1.3.1 保持插入顺序:操作演示
        • 1.3.2 移除最后/最前元素:`popitem`方法
        • 1.3.3 用途:记录操作历史等
      • 1.4 `defaultdict`:默认值字典
        • 1.4.1 默认工厂函数:`int`、`list`、`lambda`
        • 1.4.2 键不存在时的处理:自动返回默认值
        • 1.4.3 适用场景:缺失键的字典操作
      • 1.5 `namedtuple`:命名元组
        • 1.5.1 字段化元组:定义和使用
        • 1.5.2 字段访问:代替索引
        • 1.5.3 实际应用:简单数据对象
      • 二. `heapq`模块:优先队列与排序的利器
        • 2.1 堆的基本概念
        • 2.2 `heapq`模块的使用
        • 2.3 小顶堆与大顶堆实例
        • 2.4 实际应用场景
      • 三. 拓展阅读
        • 3.1 `array`模块:紧凑数组
        • 3.2 `functools`模块:高阶函数
        • 3.3 `itertools`模块:迭代器工具
      • 总结

一. collections模块:数据结构的瑞士军刀

1.1 deque:双端队列

dequecollections模块中提供的一种数据结构,代表了一个双端队列(double-ended queue)。它可以在两端高效地插入和删除元素,具有较好的性能。

deque支持以下主要操作:

  • append(x):将元素x添加到队列的右侧(末尾)。
  • appendleft(x):将元素x添加到队列的左侧(开头)。
  • pop():从队列的右侧(末尾)弹出并返回一个元素。
  • popleft():从队列的左侧(开头)弹出并返回一个元素。
  • extend(iterable):在队列的右侧(末尾)追加可迭代对象中的所有元素。
  • extendleft(iterable):在队列的左侧(开头)追加可迭代对象中的所有元素。
  • rotate(n):向右循环移动队列中的元素,若n>0,则右侧的n个元素将移动到左侧;若n<0,则左侧的abs(n)个元素将移动到右侧。
1.1.1 操作示例:插入、删除、迭代
from collections import deque

# 创建一个双端队列
queue = deque()

# 添加元素到队列的末尾
queue.append(1)
queue.append(2)

# 从队列的开头弹出元素
item = queue.popleft()
print(item)  # 输出: 1
1.1.2 高效性能:与列表比较
# 对比使用列表和deque进行频繁插入和删除操作的性能差异

from collections import deque
import timeit

# 使用列表进行插入和删除
def list_operations():
    my_list = []
    for i in range(10000):
        my_list.append(i)
    for _ in range(10000):
        my_list.pop(0)

# 使用deque进行插入和删除
def deque_operations():
    my_deque = deque()
    for i in range(10000):
        my_deque.append(i)
    for _ in range(10000):
        my_deque.popleft()

# 计算列表操作时间
list_time = timeit.timeit(list_operations, number=1000)

# 计算deque操作时间
deque_time = timeit.timeit(deque_operations, number=1000)

print(f"使用列表的操作时间:{list_time} 秒")
print(f"使用deque的操作时间:{deque_time} 秒")

在这里插入图片描述

1.1.3 应用场景:广度优先搜索(BFS)等
# 演示在广度优先搜索算法中使用deque的场景

from collections import deque

# 定义图的邻接表表示
graph = {
    'A': ['B', 'C'],
    'B': ['D', 'E'],
    'C': ['F', 'G'],
    'D': [],
    'E': [],
    'F': [],
    'G': []
}

def bfs(graph, start):
    visited = set()
    queue = deque([start])

    while queue:
        node = queue.popleft()
        if node not in visited:
            print(node, end=' ')
            visited.add(node)
            queue.extend(set(graph[node]) - visited)

# 从顶点'A'开始进行广度优先搜索
print("广度优先搜索结果:", end='')
bfs(graph, 'A')

以上代码演示了deque相对于列表在频繁插入和删除操作中的性能优势,并展示了在广度优先搜索算法中使用deque处理状态空间遍历的场景。deque在这些场景中表现出色,是一个高效的数据结构选择。

在这里插入图片描述

接下来,我们将深入探讨上述内容,逐一展开具体的细节和代码示例。

1.2 Counter:计数器

Countercollections模块中提供的一种数据结构,用于计数可哈希对象的出现次数。它可以方便地统计元素的频率。

Counter是一个字典(dict)的子类,其中元素作为键,它们的出现次数作为值。它支持基本的字典操作,例如添加元素、删除元素和迭代访问等。

Counter支持以下主要操作:

  • update(iterable):从可迭代对象中更新计数器,将每个元素视为一个计数项。
  • elements():返回一个迭代器,按照计数的重复次数重复每个元素。
  • most_common(n=None):返回一个列表,包含计数最高的前n个元素及其对应的计数,按计数从高到低排序。
1.2.1 统计频率:文本处理、数据分析

Counter是一个强大的工具,用于统计可哈希对象的出现次数。这在文本处理、数据分析等领域非常有用。以下是一个简单的示例:

from collections import Counter

# 创建计数器
counter = Counter()

# 计数元素
counter.update([1, 1, 2, 3, 3, 3])

# 获取元素出现次数
count = counter[1]
print(count)  # 输出: 2

在这个例子中,我们创建了一个计数器 counter,然后使用 update 方法更新计数器的内容。最后,我们通过索引获取特定元素的出现次数。

1.2.2 更新计数器:可迭代对象的应用

Counter通过 update 方法支持从可迭代对象中更新计数。这使得处理大规模数据时变得非常方便:

from collections import Counter

# 创建计数器
counter = Counter()

# 使用update方法从可迭代对象更新计数
data = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
counter.update(data)

print(counter)
# 输出: Counter({4: 4, 3: 3, 2: 2, 1: 1})
1.2.3 实用技巧:找出最常见的元素

most_common 方法返回计数最高的前 n 个元素及其对应的计数,按计数从高到低排序。这在需要确定数据中频繁出现的元素时非常有用:

from collections import Counter

# 创建计数器
counter = Counter()

# 计数元素
counter.update([1, 1, 2, 3, 3, 3])

# 获取最常见的元素
most_common = counter.most_common(2)
print(most_common)  # 输出: [(3, 3), (1, 2)]

通过这些实用技巧,Counter在处理数据频率统计时表现出色,为数据分析和处理提供了便捷的工具。

1.3 OrderedDict:有序字典

OrderedDictcollections模块中提供的一种数据结构,它是一个有序的字典(dict)。与普通字典不同,OrderedDict记住了元素插入的顺序,因此可以按照插入的顺序遍历和访问元素。

除了支持普通字典的所有操作,OrderedDict还提供以下额外的功能:

  • popitem(last=True):移除并返回最后一个(默认)或第一个键值对。
  • move_to_end(key, last=True):将指定的键移动到字典的末尾(默认)或开头。
  • clear():清空字典中的所有键值对。
1.3.1 保持插入顺序:操作演示

OrderedDict是一个有序字典,可以按照元素插入的顺序进行遍历。这在需要记住操作历史等场景非常有用:

from collections import OrderedDict

# 创建有序字典
ordered_dict = OrderedDict()

# 添加键值对
ordered_dict['a'] = 1
ordered_dict['b'] = 2
ordered_dict['c'] = 3

# 按照插入顺序遍历键值对
for key, value in ordered_dict.items():
    print(key, value)  # 输出: a 1, b 2, c 3
1.3.2 移除最后/最前元素:popitem方法

OrderedDict提供了 popitem 方法,可以移除并返回最后一个或第一个键值对,为字典操作提供了额外的操作灵活性:

from collections import OrderedDict

# 创建有序字典
ordered_dict = OrderedDict()

# 添加键值对
ordered_dict['a'] = 1
ordered_dict['b'] = 2
ordered_dict['c'] = 3

# 移除并返回最后一个键值对
last_item = ordered_dict.popitem(last=True)
print(last_item)  # 输出: ('c', 3)

# 移除并返回第一个键值对
first_item = ordered_dict.popitem(last=False)
print(first_item)  # 输出: ('a', 1)
1.3.3 用途:记录操作历史等

OrderedDict在需要保持元素顺序的情况下非常有用。它可以用于构建记录操作顺序的日志、维护缓存中最近访问的元素等场景。通过记录操作历史,我们可以更好地理解和追踪程序的执行流程。

1.4 defaultdict:默认值字典

defaultdictcollections模块中提供的一种数据结构,它是一个字典(dict)的子类,可以为字典中的键提供默认值。当访问一个不存在的键时,defaultdict会自动返回指定的默认值,而不会抛出KeyError异常。

要使用defaultdict,需要提供一个可调用对象作为默认工厂函数。这个工厂函数将在访问不存在的键时被调用,以生成默认值。常见的默认工厂函数包括intlistlambda等。

1.4.1 默认工厂函数:intlistlambda

defaultdict是一个带有默认值的字典,可以为字典中的键提供默认值。我们可以使用内置类型(如 intlist)或自定义函数作为默认工厂函数:

from collections import defaultdict

# 创建带有默认值的字典,默认值为0
default_dict_int = defaultdict(int)

# 创建带有默认值的字典,默认值为空列表
default_dict_list = defaultdict(list)

# 创建带有默认值的字典,自定义默认值生成规则
default_dict_lambda = defaultdict(lambda: 'default_value')
1.4.2 键不存在时的处理:自动返回默认值

defaultdict通过指定的默认工厂函数,在访问不存在的键时自动生成默认值。这样,我们可以避免在代码中频繁检查键是否存在:

from collections import defaultdict

# 创建带有默认值的字典,默认值为0
default_dict = defaultdict(int)

# 访问不存在的键,返回默认值
count = default_dict['a']
print(count)  # 输出: 0
1.4.3 适用场景:缺失键的字典操作

defaultdict非常适合在处理字典中缺失键的情况下使用。它可以简化对键是否存在的检查并提供默认值,避免了频繁使用 if-else 语句的麻烦。这在处理各种数据时非常实用,特别是在数据处理流程中,当我们需要为缺失的键提供默认值时,defaultdict可以提供一种更加简洁和高效的解决方案。让我们来看一些具体的应用场景和代码示例:

from collections import defaultdict

# 1. 创建带有默认值的字典,默认值为空列表
default_dict_list = defaultdict(list)

# 2. 向字典添加数据,无需检查键是否存在
default_dict_list['fruits'].append('apple')
default_dict_list['fruits'].append('banana')

default_dict_list['vegetables'].append('carrot')

# 输出带有默认值的字典
print(default_dict_list)
# 输出: defaultdict(<class 'list'>, {'fruits': ['apple', 'banana'], 'vegetables': ['carrot']})

在这个例子中,我们创建了一个 defaultdict,其默认值为一个空列表。然后,我们向字典中添加水果和蔬菜的数据,而无需检查键是否存在。这简化了代码,并使我们能够更专注于数据操作而不是键的存在性检查。

1.5 namedtuple:命名元组

namedtuplecollections模块中提供的一种数据结构,它是一个具有字段名称的元组。与普通元组不同,namedtuple中的每个元素都可以通过字段名称进行访问和使用,而无需依赖索引。

使用namedtuple时,首先需要定义一个命名元组类,并指定字段的名称。然后可以使用该类来创建命名元组的实例。每个字段在创建实例时都可以赋值,方便地访问和操作字段值。

1.5.1 字段化元组:定义和使用

namedtuple提供了一种更具可读性的元组,通过字段名称而不是索引来访问元素。这在表示简单数据对象时非常有用:

from collections import namedtuple

# 定义第一个命名元组类
Person = namedtuple('Person', ['name', 'age'])

# 创建第一个命名元组实例
person = Person(name='Alice', age=25)

# 访问第一个命名元组实例的字段
print(person.name)  # 输出: Alice
print(person.age)   # 输出: 25
1.5.2 字段访问:代替索引

通过给元组的各个字段赋予名称,我们避免了依赖于位置索引的问题,提高了代码的可读性和可维护性:

from collections import namedtuple

# 定义第二个命名元组类
Point = namedtuple('Point', ['x', 'y', 'z'])

# 创建第二个命名元组实例
point = Point(x=1, y=2, z=3)

# 访问第二个命名元组实例的字段
print(point.x)  # 输出: 1
print(point.y)  # 输出: 2
print(point.z)  # 输出: 3
1.5.3 实际应用:简单数据对象

namedtuple常用于表示简单的数据对象,例如二维坐标、日期记录等。通过字段名称,可以更清晰地表达数据的含义,提高代码的可读性:

from collections import namedtuple

# 定义日期记录的命名元组类
DateRecord = namedtuple('DateRecord', ['year', 'month', 'day'])

# 创建日期记录的命名元组实例
date = DateRecord(year=2023, month=11, day=13)

# 访问日期记录的字段
print(date.year)   # 输出: 2023
print(date.month)  # 输出: 11
print(date.day)    # 输出: 13

通过这些例子,我们可以看到 namedtuple 如何提高代码的清晰度和可读性,特别是在表示简单数据结构时。这使得代码更易于维护和理解。

二. heapq模块:优先队列与排序的利器

heapq是Python中的一个模块,提供了对堆数据结构的支持,以及在堆上执行的一些常见操作。堆是一种特殊的二叉树结构,具有以下特点:

  • 堆是一个完全二叉树,即除了最底层外,其他层都被元素填满,并且最底层从左到右填入。
  • 堆中的每个节点的值大于或等于(最大堆)或小于或等于(最小堆)其子节点的值。

heapq模块提供了一系列函数来创建和操作堆:

  • heappush(heap, item):将元素item添加到堆heap中。
  • heappop(heap):从堆heap中弹出并返回最小(或最大)的元素。
  • heapify(x):将可迭代对象x转换为堆数据结构。
  • heappushpop(heap, item):将元素item添加到堆heap中,并弹出并返回堆中的最小(或最大)元素。
  • heapreplace(heap, item):弹出并返回堆中的最小(或最大)元素,然后将元素item添加到堆中。
2.1 堆的基本概念
  • 2.1.1 完全二叉树:堆的基本结构
    堆是一种完全二叉树,节点排列方式确保在插入和删除元素时保持堆的性质。

    # 示例:创建一个小顶堆
    import heapq
    
    heap = []
    heapq.heappush(heap, 5)
    heapq.heappush(heap, 2)
    heapq.heappush(heap, 10)
    print(heap)  # 输出: [2, 5, 10]
    
  • 2.1.2 小顶堆与大顶堆:堆的种类
    小顶堆:每个节点值不大于其子节点值。

    大顶堆:每个节点值不小于其子节点值。

    # 示例:创建一个大顶堆
    import heapq
    
    heap = []
    for num in [5, 2, 10]:
        heapq.heappush(heap, -num)
    largest = -heapq.heappop(heap)
    print(largest)  # 输出: 10
    
2.2 heapq模块的使用
  • 2.2.1 heappushheappop:插入与删除

    import heapq
    
    heap = []
    heapq.heappush(heap, 5)
    heapq.heappush(heap, 2)
    heapq.heappush(heap, 10)
    
    min_element = heapq.heappop(heap)
    print(min_element)  # 输出: 2
    
  • 2.2.2 heapify函数:转换为堆

    import heapq
    
    x = [3, 1, 6, 4]
    heapq.heapify(x)
    print(x)  # 输出: [1, 3, 6, 4]
    
  • 2.2.3 heappushpopheapreplace:替换元素

    import heapq
    
    heap = [5, 7, 9, 4, 3]
    new_element = 6
    
    # 替换并返回堆中的最小元素
    replaced = heapq.heappushpop(heap, new_element)
    print(replaced)  # 输出: 4
    
    # 插入元素并返回堆中的最小元素
    replaced = heapq.heapreplace(heap, new_element)
    print(replaced)  # 输出: 5
    
2.3 小顶堆与大顶堆实例
  • 2.3.1 操作示例:插入、弹出等

    import heapq
    
    # 小顶堆示例
    min_heap = []
    heapq.heappush(min_heap, 5)
    heapq.heappush(min_heap, 2)
    heapq.heappush(min_heap, 10)
    min_element = heapq.heappop(min_heap)
    print(min_element)  # 输出: 2
    
    # 大顶堆示例
    max_heap = []
    for num in [5, 2, 10]:
        heapq.heappush(max_heap, -num)
    largest = -heapq.heappop(max_heap)
    print(largest)  # 输出: 10
    
  • 2.3.2 独立文件示例:min_heap.pymax_heap.py
    小顶堆和大顶堆的操作分别存储在独立的文件中,提高代码可维护性。

min_heap.py

import heapq

def main():
    # 初始化小顶堆
    min_heap = []

    # 待插入小顶堆的元素
    elements = [1, 3, 2, 5, 4]

    print("小顶堆:")
    for element in elements:
        heapq.heappush(min_heap, element)
        print(f"插入 {element} 到小顶堆:", min_heap)

    # 获取小顶堆的顶部元素
    min_peek = min_heap[0]
    print(f"\n小顶堆顶部元素:{min_peek}")

    print("\n小顶堆弹出元素:")
    while min_heap:
        popped_element = heapq.heappop(min_heap)
        print(f"弹出元素: {popped_element},当前小顶堆:", min_heap)

if __name__ == "__main__":
    main()

max_heap.py

import heapq

def main():
    # 初始化大顶堆
    max_heap = []

    # 待插入大顶堆的元素
    elements = [1, 3, 2, 5, 4]

    print("大顶堆:")
    for element in elements:
        heapq.heappush(max_heap, -element)
        print(f"插入 {-element} 到大顶堆:", [-x for x in max_heap])

    # 获取大顶堆的顶部元素
    max_peek = -max_heap[0]
    print(f"\n大顶堆顶部元素:{max_peek}")

    print("\n大顶堆弹出元素:")
    while max_heap:
        popped_element = -heapq.heappop(max_heap)
        print(f"弹出元素: {popped_element},当前大顶堆:", [-x for x in max_heap])

if __name__ == "__main__":
    main()

你可以单独运行 min_heap.pymax_heap.py 来观察小顶堆和大顶堆的行为。打印语句将在执行每个操作后显示堆的内容。
小顶堆和大顶堆是一种特殊的二叉堆,它们具有以下性质:

  • 小顶堆:每个节点的值都不大于其子节点的值,即父节点的值小于或等于左右子节点的值。
  • 大顶堆:每个节点的值都不小于其子节点的值,即父节点的值大于或等于左右子节点的值。

这里我们使用了Python的heapq模块来实现堆操作。

小顶堆的原理及操作步骤:

  1. 初始化一个空列表作为小顶堆:min_heap = []
  2. 使用heappush函数将元素插入小顶堆。插入元素时,会保持堆结构的性质,即依次比较新元素与当前堆中的元素,并进行必要的交换,以保证小顶堆的性质。
  3. 通过访问min_heap[0]可以获取小顶堆的最小值,也即堆顶元素。
  4. 使用heappop函数弹出小顶堆的堆顶元素。弹出操作会移除堆顶元素,并且会重新调整剩余元素的顺序,使其满足小顶堆的性质。
  5. 可以使用heapify函数将一个普通列表转换为小顶堆。
  6. 重复步骤2到5,直到小顶堆为空。

大顶堆的原理及操作步骤:

  1. 初始化一个空列表作为大顶堆:max_heap = []
  2. 在插入元素时,我们需要将元素的值取负值来实现大小关系的颠倒。即使用heappush函数将 -element 插入大顶堆中。
  3. 通过访问 -max_heap[0] 可以获取大顶堆的最大值,也即堆顶元素。
  4. 使用 heappop 函数弹出大顶堆的堆顶元素时,需要再次取负值才能得到正确的值,即 -heapq.heappop(max_heap)
  5. 其余操作与小顶堆相同。

这样,我们就可以利用小顶堆和大顶堆进行高效的数据处理,包括插入、删除和查找等操作。

2.4 实际应用场景
  • 2.4.1 优先队列:任务调度等
    小顶堆常用于实现优先队列,用于任务调度等场景。

    import heapq
    
    class PriorityQueue:
        def __init__(self):
            self.heap = []
    
        def push_task(self, priority, task):
            heapq.heappush(self.heap, (priority, task))
    
        def pop_task(self):
            priority, task = heapq.heappop(self.heap)
            return task
    
    # 示例
    priority_queue = PriorityQueue()
    priority_queue.push_task(2, 'Task 1')
    priority_queue.push_task(1, 'Task 2')
    priority_queue.push_task(3, 'Task 3')
    
    next_task = priority_queue.pop_task()
    print(next_task)  # 输出: Task 2
    
  • 2.4.2 排序算法:堆排序实现

 import heapq

 def heap_sort(arr):
     heap = arr.copy()
     heapq.heapify(heap)
     sorted_arr = [heapq.heappop(heap) for _ in range(len(heap))]
     return sorted_arr

 # 示例
 unsorted_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
 sorted_list = heap_sort(unsorted_list)
 print(sorted_list)  # 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

三. 拓展阅读

3.1 array模块:紧凑数组
  • 3.1.1 array的创建与基本操作
    array模块提供了一种紧凑的数组结构,可以在性能和内存占用之间找到平衡。

    from array import array
    
    # 创建一个双精度浮点数数组
    double_array = array('d', [1.2, 3.4, 5.6])
    
    # 访问数组元素
    first_element = double_array[0]
    print(first_element)  # 输出: 1.2
    
  • 3.1.2 与列表的比较与应用
    比较array和列表的性能特点,并介绍array在某些场景下的应用。

    from array import array
    import time
    
    # 使用列表存储一百万个双精度浮点数
    list_numbers = [i * 0.1 for i in range(1000000)]
    
    # 使用数组存储一百万个双精度浮点数
    array_numbers = array('d', [i * 0.1 for i in range(1000000)])
    
    # 比较列表和数组的索引操作性能
    start_time = time.time()
    for _ in range(100000):
        _ = list_numbers[500000]
    list_time = time.time() - start_time
    
    start_time = time.time()
    for _ in range(100000):
        _ = array_numbers[500000]
    array_time = time.time() - start_time
    
    print(f'列表索引操作耗时: {list_time} 秒')
    print(f'数组索引操作耗时: {array_time} 秒')
    
3.2 functools模块:高阶函数
  • 3.2.1 functools.partial:部分应用函数
    functools.partial允许我们部分应用函数,固定部分参数,从而派生出新的函数。

    from functools import partial
    
    # 定义一个简单的函数
    def power(base, exponent):
        return base ** exponent
    
    # 使用partial固定exponent参数
    square = partial(power, exponent=2)
    
    # 调用新的函数
    result = square(5)
    print(result)  # 输出: 25
    
  • 3.2.2 使用示例:定制排序函数
    演示如何使用functools.partial创建定制的排序函数,以便满足不同的排序需求。

    from functools import partial
    
    # 列表中的元素是字典
    students = [
        {'name': 'Alice', 'score': 90},
        {'name': 'Bob', 'score': 85},
        {'name': 'Charlie', 'score': 95}
    ]
    
    # 使用partial创建定制的排序函数
    sort_by_score = partial(sorted, key=lambda x: x['score'])
    
    # 按分数排序学生
    sorted_students = sort_by_score(students)
    print(sorted_students)
    
3.3 itertools模块:迭代器工具
  • 3.3.1 countcycle:无限迭代器
    itertools.count生成无限递增的整数序列,而itertools.cycle则无限重复给定的可迭代对象。

    from itertools import count, cycle
    
    # 生成无限递增的整数序列
    for i in count(1):
        print(i)
        if i == 5:
            break
    
    # 无限循环重复给定的可迭代对象
    values = [1, 2, 3]
    for val in cycle(values):
        print(val)
        if val == 3:
            break
    
  • 3.3.2 zip_longest:等长迭代器
    itertools.zip_longest用于将多个可迭代对象逐个组合成元组,确保结果的长度与最长的输入相等。

    from itertools import zip_longest
    
    # 等长迭代器
    numbers = [1, 2, 3]
    letters = ['a', 'b']
    zipped = zip_longest(numbers, letters, fillvalue=None)
    
    for item in zipped:
        print(item)
    

以上是对arrayfunctoolsitertools模块的简要介绍,包含了基本的使用和一些实际场景的示例。如有需要,可以进一步深入学习这些模块的更多功能。

总结

collectionsheapq模块不仅是Python语言的标配工具,更是解决算法和数据处理难题的得力助手。通过深入学习这些模块提供的数据结构和操作,我们能够更加优雅地编写代码,提高程序的执行效率。从双端队列到堆的引入,本文将带领读者深入理解这些工具,并展示它们在实际场景中的强大应用。

希望读者通过本文的学习,能够在日常编程中更灵活地选择和使用适当的数据结构,从而提升代码的可读性和性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/139688.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

竞赛 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现

文章目录 0 前言1 项目背景2 算法架构3 FP-Growth算法原理3.1 FP树3.2 算法过程3.3 算法实现3.3.1 构建FP树 3.4 从FP树中挖掘频繁项集 4 系统设计展示5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于FP-Growth的新闻挖掘算法系统的设计与实现…

JavaScript 基本数据类型

字符串 在JS中&#xff0c;数据类型有&#xff1a;字符串、数字、布尔、数组、对象、Null、Undefined 用到最多的还是字符串和数组的转换。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</title><style&g…

Rust语言做数据抓取代码示例

这个任务需要使用到Rust语言和网络爬虫相关的库&#xff0c;以下是一个简单的示例代码。请注意&#xff0c;由于涉及到的具体问题和数据的复杂性&#xff0c;这个示例可能并不能直接满足你的需求&#xff0c;需要根据你的具体情况进行修改和扩展。 use reqwest; use serde::{De…

Splashtop 如何维护 GDPR 合规性

2018年&#xff0c;欧盟颁布了一项新法律&#xff0c;以保护欧洲公民的个人数据免遭任何收集数据的人不当处理。这可能意味着企业和组织&#xff0c;包括面对面和虚拟形式。这项开创性的法律为其他立法铺平了道路&#xff0c;例如加利福尼亚州的《加州消费者隐私法》&#xff0…

linux线程

文章目录 前言一、线程1、线程概念2、线程使用2.1 pthread_create2.2 线程共享数据和私有数据2.3 为什么线程切换的成本更低&#xff1f; 3、线程性质3.1 线程的优点3.2 线程的缺点3.3 线程异常3.4 线程用途 4、vfork接口 二、线程控制1、线程创建2、线程等待3、线程退出4、线程…

行业追踪,2023-11-13

自动复盘 2023-11-13 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

集成Line、Facebook、Twitter、Google、微信、QQ、微博、支付宝的三方登录sdk

下载地址&#xff1a; https://githubfast.com/anerg2046/sns_auth 安装方式建议使用composer进行安装 如果linux执行composer不方便的话&#xff0c;可以在本地新建个文件夹&#xff0c;然后执行上面的composer命令&#xff0c;把代码sdk和composer文件一起上传到项目适当位…

【STM32】定时器+基本定时器

一、定时器的基本概述 1.软件定时器原理 原来我们使用51单片机的时候&#xff0c;是通过一个__nop()__来进行延时 我们通过软件的方式来进行延时功能是不准确的&#xff0c;受到很多不确定因素。 2.定时器原理&#xff1a;计数之间的比值 因为使用软件延时受到影响&#xff0c…

Scala---介绍及安装使用

一、Scala介绍 1. 为什么学习Scala语言 Scala是基于JVM的语言&#xff0c;与java语言类似&#xff0c;Java语言是基于JVM的面向对象的语言。Scala也是基于JVM&#xff0c;同时支持面向对象和面向函数的编程语言。这里学习Scala语言的原因是后期我们会学习一个优秀的计算框架S…

企业如何管理员工电脑和规范电脑的使用

企业如何管理员工电脑和规范电脑的使用 在现代信息时代&#xff0c;数据安全问题已经成为各个领域都面临的挑战。随着大数据的快速发展和互联网的普及&#xff0c;数据泄露的风险也逐渐增加。而作为企业或个人用户&#xff0c;如何保护自己的数据&#xff0c;避免泄露给不法分…

ios 对话框UIAlertController放 tableview

//强弱引用 #define kWeakSelf(type)__weak typeof(type)weak##type type; -(void) showUIAlertTable {kWeakSelf(self)UIAlertController *alert [UIAlertController alertControllerWithTitle:NSLocalizedString("select_stu", nil) message:nil prefer…

构建Docker基础镜像(ubuntu20.04+python3.9.10+pytorch-gpu-cuda11.8)

文章目录 一、前置条件1.创建 ubuntu 镜像源文件【sources.list】2.下载 python 安装包【Python-3.9.10.tgz】 二、构建方法1.构建目录2.创建DockerFile3.打包镜像 一、前置条件 配置一下 ubuntu 的镜像源下载 python 安装包 1.创建 ubuntu 镜像源文件【sources.list】 内容…

麒麟信安登录央视,深度展现为中国信息安全铸“魂”之路

麒麟信安登录央视&#xff0c;深度展现为中国信息安全铸“魂”之路 近日&#xff0c;麒麟信安登录央视频道&#xff0c;《麒麟信安——为中国信息安全铸“魂”》在CCTV-4中文国际频道、CCTV-7国防军事频道、CCTV-10 科教频道、CCTV-12社会与法频道、CCTV-17农业农村频道&#x…

动态调整学习率Lr

动态调整学习率Lr 0 引入1 代码例程1.1 工作方式解释 2 动态调整学习率的几种方法2.1 lr_scheduler.LambdaLR2.2 lr_scheduler.StepLR2.3 lr_scheduler.MultiStepLR2.4 lr_scheduler.ExponentialLR2.2.5 lr_scheduler.CosineAnnealingLR2.6 lr_scheduler.ReduceLROnPlateau2.7 …

后门程序2

System\CurrentControlSet\Services\Disk\Enum Windows 操作系统注册表中的一个路径。这个路径通常包含有关磁盘设备的信息。在这个特定的路径下&#xff0c;可能存储了有关磁盘枚举的配置和参数 Enum&#xff08;枚举&#xff09;子键通常包含了系统对磁盘的枚举信息&#xf…

网络安全/黑客技术(0基础入门到进阶提升)

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c;但是连方向都没搞清楚就开始学习…

高通SDX12:ASoC 音频框架浅析

一、简介 ASoC–ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。 本文基于高通SDX12平台,对ASoC框架做一个分析。 二、整体框架 1. 硬件层面 嵌入式Linux设备的Audio subsystem可以划分为Machine(板…

关于企业海外Social平台营销布局,你需要了解这三件事

01 企业Social营销布局模式 Social营销走到现在&#xff0c;早已进入了标准配置期。任何企业和组织&#xff0c;进行营销宣传的时候都会在社媒社交平台上创建账号和运营。目前&#xff0c;海外Social平台营销模式基本分为四类&#xff1a; 官方社媒账号运营&#xff1a;以Hoot…

HTML5学习系列之主结构

HTML5学习系列之主结构 前言HTML5主结构定义页眉定义导航定义主要区域定义文章块定义区块定义附栏定义页脚 具体使用总结 前言 学习记录 HTML5主结构 定义页眉 head表示页眉&#xff0c;用来表示标题栏&#xff0c;引导和导航作用的结构元素。 <header role"banner…

使用Python和requests库的简单爬虫程序

这是一个使用Python和requests库的简单爬虫程序。我们将使用代理来爬取网页内容。以下是代码和解释&#xff1a; import requests from fake_useragent import UserAgent # 每行代理信息 proxy_host "jshk.com.cn" # 创建一个代理器 proxy {http: http:// proxy_…