像大神一样使用和操作Python迭代器

像大神一样使用和操作Python迭代器

在 Python 编程中,理解并有效使用迭代表是熟练编码的基础。迭代表是可以遍历或循环的对象。它们支持对其中的元素进行顺序遍历,是访问和操作对象或数据结构中元素的重要工具。

本文通过重点介绍 Python 语言的内置可遍历数据类型:列表、元组、字典、字符串和集合,探讨了如何正确使用 Python 可遍历对象。它还解释了如何实现自定义可遍历类型和执行高级操作。

如何遍历 Python 可迭代类型

在 Python 中,您可以使用 for 循环遍历各种可遍历类型。这使您能够浏览序列,并对列表、集合和字典中的单个项执行操作。

Python 中的 for 关键字与 Java 等其他面向对象语言中的 for 关键字不同。Python for 循环的工作方式更像是迭代器方法。下面的示例演示了迭代表中的循环:

1. 在列表中循环

列表是有序的项目集合,可以使用 for 循环轻松迭代。

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for fruit in fruits_list:
print(fruit)

在上面的代码中, fruit 充当迭代器,循环使用它来遍历每个列表元素,同时打印它们。循环在评估完列表中的最后一个元素后终止。上述代码的输出结果如下

Apple
Mango
Peach
Orange
Banana

2. 迭代元组

元组与列表类似,但不可变。您可以像遍历列表一样遍历元组。

fruits_tuple = ("Apple", "Mango", "Peach", "Orange", "Banana")
for fruit in fruits_tuple:
print(fruit)

在此示例中, for 循环遍历元组,在每次遍历中,变量 fruit 取元组中当前元素的值。代码输出如下:

Apple
Mango
Peach
Orange
Banana

3. 循环浏览集合

集合是由唯一元素组成的无序集合。您可以使用 for 循环遍历它们。

fruits_set = {"Apple", "Mango", "Peach", "Orange", "Banana"}
for fruit in fruits_set:
print(fruit)

在本例中, for 循环对集合进行迭代。但是,由于集合是无序的,迭代的顺序可能与集合中定义元素的顺序不同。在每次迭代中,变量 fruit 都会取集合中当前元素的值。代码的输出结果应与下面类似(顺序可能不同):

Mango
Banana
Peach
Apple
Orange

4. 遍历字符串

字符串是字符序列,可以逐个字符循环。

string = "Kinsta"
for char in string:
print(char)

上面的代码遍历字符串 “Wbolt”,并将每个字符打印到新行上。在每次迭代中,变量 char 的值都是字符串中当前字符的值。代码的输出结果如下

W
b
o
l
t

5. 遍历字典

对于列表、集合、元组和字符串来说, for 循环的使用方法类似,但对于字典来说就不同了,因为字典使用键值对来存储条目。字典是一个独特的循环案例,因为你可以使用不同的方法遍历字典。下面是您可以用来遍历 Python 字典的不同方法:

按键迭代:

countries_capital = {
"USA": "Washington D.C.",
"Australia": "Canberra",
"France": "Paris",
"Egypt": "Cairo",
"Japan": "Tokyo"
}
for country in countries_capital.keys():
print(country)

上面的代码定义了一个名为 countries_capital 的字典,其中国家名称是键,它们各自的首都是值。for 循环使用 keys() 方法遍历 countries_capital 字典中的键。该方法会返回一个视图对象,显示字典中的键值列表,这样就可以方便地循环查看所有键值。在每次迭代中,变量 country 都取当前键的值。这段代码的输出结果如下:

USA
Australia
France
Egypt
Japan

迭代数值:

countries_capital = {
"USA": "Washington D.C.",
"Australia": "Canberra",
"France": "Paris",
"Egypt": "Cairo",
"Japan": "Tokyo"
}
for capital in countries_capital.values():
print(capital)

在上面的代码中, for 使用 values() 方法遍历 countries_capital 字典中的值。该方法返回一个视图对象,显示字典中的值的列表,便于循环查看所有值。在每次迭代中,变量 capital 都会取列表中当前值的值。这段代码的输出结果如下

Washington D.C.
Canberra
Paris
Cairo
Tokyo

遍历键值对:

countries_capital = {
"USA": "Washington D.C.",
"Australia": "Canberra",
"France": "Paris",
"Egypt": "Cairo",
"Japan": "Tokyo"
}
for country, capital in countries_capital.items():
print(country, ":", capital)

上面的代码演示了如何使用 items() 方法遍历 countries_capital 字典的键和值。 items()  方法返回一个视图对象,显示字典中键值元组的列表。在 for 循环中,每次迭代都会从列表中的当前元素解包一个键值对。变量 countrycapital 分别被赋予相应的键和值。这段代码的输出结果如下:

USA : Washington D.C.
Australia : Canberra
France : Paris
Egypt : Cairo
Japan : Tokyo

用 Python 中的 enumerate() 进行高级迭代

在返回元素索引和相应值的同时遍历 Python 可迭代表的另一种方法是使用 enumerate() 函数。请看这个示例:

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for index, fruit in enumerate(fruits_list):
print(fruit, index)

 

输出结果如下:

Apple 0
Mango 1
Peach 2
Orange 3
Banana 4

 

enumerate 函数还允许您指定迭代操作的起始索引( 0 除外)。您可以将上面的示例修改如下:

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for index, fruit in enumerate(fruits_list, start = 2):
print(fruit, index)

 

输出结果如下:

Apple 2
Mango 3
Peach 4
Orange 5
Banana 6

 

请注意,虽然本示例指定了枚举的起始索引,但 enumerate 并不像本地列表那样对可迭代元素应用基于零的索引。它只是将起始值附加到列表中的第一个元素,直到最后一个元素。

如何实现 Python 生成器

生成器是一种特殊的 Python 可迭代对象,它允许您构建生成器对象,而无需显式地创建内置类型,如列表、集合或字典。您可以使用生成器来根据生成逻辑生成值。

生成器使用 yield 语句一次返回一个生成值。下面是一个生成器迭代的示例:

def even_generator(n):
counter = 0
while counter <= n:
if counter % 2 == 0:
yield counter
counter += 1
for num in even_generator(20):
print(num)

提供的代码定义了一个 even_generator 函数,该函数使用 yield 语句生成从 0 到指定 n 的偶数序列。它利用循环生成这些值,并使用 num 迭代器遍历结果,确保对给定范围内的所有值进行评估。如下所示,这段代码将输出一个从 020 的偶数列表:

0
2
4
6
8
10
12
14
16
18
20

在使用生成器表达式时,您可以获得更简洁的效果。例如,您可以设计一个同时包含循环逻辑的生成器函数:

cube = (num ** 3 for num in range(1, 6))
for c in cube:
print(c)

在这里,你将变量 cube 赋值给一个函数的结果,该函数计算 1 到 6 范围内数值的立方。然后在指定范围内循环取值,一个接一个地输出计算结果。输出结果如下:

1
8
27
64
125

如何构建自定义迭代器

Python 允许您使用迭代器进一步自定义可迭代操作。迭代器对象实现了迭代器协议,并包含 2 个方法: __iter__()__next__()__iter__() 方法返回一个迭代器对象,而 __next__() 方法返回迭代器容器中的下一个值。下面是 Python 中的一个迭代器示例:

even_list = [2, 4, 6, 8, 10]
my_iterator = iter(even_list)
print(next(my_iterator)) # Prints 2
print(next(my_iterator)) # Prints 4
print(next(my_iterator)) # Prints 6

在这个示例中,你使用 iter() 方法从列表中创建了一个迭代器对象( my_iterator )。要访问列表中的每个元素,需要用 next() 方法封装迭代器对象。由于列表是有序集合,因此迭代器会按顺序返回元素。

自定义迭代器非常适合涉及无法同时加载到内存中的大型数据集的操作。由于内存昂贵且容易受到空间限制,因此可以使用迭代器单独处理数据元素,而无需将整个数据集加载到内存中。

可迭代函数

Python 使用函数来移动、操作和检查列表元素。一些常用的 list 函数包括:

  • sum — 返回给定可迭代元素的总和,前提是集合为数值类型(整数、浮点数和复数)
  • any — 如果可迭代元素中有任何元素为真,则返回 true。否则返回 false 值。
  • all — 如果所有可迭代元素都为真,则返回 true。否则,返回 false
  • max — 返回给定可迭代集合的最大值
  • min — 返回给定可迭代集合的最小值
  • len — 返回给定可迭代集合的长度
  • append — 将一个值添加到可迭代列表的末尾

下面的示例用一个列表演示了这些函数:

even_list = [2, 4, 6, 8, 10]
print(sum(even_list))
print(any(even_list))
print(max(even_list))
print(min(even_list))
even_list.append(14) # Add 14 to the end of the list
print(even_list)
even_list.insert(0, 0) # Insert 0 and specified index [0]
print(even_list)
print(all(even_list)) # Return true only if ALL elements in the list are true
print(len(even_list)) # Print the size of the list

输出结果如下:

30
True
10
2
[2, 4, 6, 8, 10, 14]
[0, 2, 4, 6, 8, 10, 14]
False
7

在上面的示例中, append 函数在列表末尾添加了一个参数( 14 )。 insert 函数允许指定插入索引。因此, even_list.insert(0, 0) 在索引 [0] 处插入了 0 。语句 print(all(even_list)) 返回 false,因为列表中有一个 0 值,解释为 false。最后, print(len(even_list)) 输出可迭代表的长度。

高级可迭代操作

Python 提供了一些高级特性,以提高可迭代操作的简洁性。下面列出了其中一些。

1. 列表综合

列表理解让您可以通过对现有列表中的每个元素应用一个函数来创建新列表。下面是一个例子:

my_numbers = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
even_number_list = [num for num in my_numbers if num%2 == 0]
print(even_number_list)

在此代码片段中,创建了一个名为 my_numbers 的列表,其中包含从 1120 的整数。目的是生成一个新的 list,即 even_number_list ,其中只包含偶数整数。要实现这一目标,需要应用列表理解,只有当 my_numbers 中的整数为偶数时,才返回该整数。 if 语句包含返回偶数的逻辑。

下面是输出结果:

[12, 14, 16, 18, 20]

2. Zip

Python 的 zip() 函数将多个迭代变量合并为元组。元组在一个变量中存储多个值,并且不可变。下面介绍如何使用 zip() 合并迭代表:

fruits = ["apple", "orange", "banana"]
rating = [1, 2, 3]
fruits_rating = zip(rating, fruits)
print(list(fruits_rating))

在本例中, fruits_rating 将每个评级与一种水果配对,创建了一个迭代。输出结果如下

[(1, 'apple'), (2, 'orange'), (3, 'banana')]

该代码是不同水果的评级系统,第一张列表(fruits)代表水果,第二张列表代表 1 到 3 级的评级。

3. Filter

另一个高级函数 filter 需要 2 个参数–一个函数和一个可迭代元素。它将函数应用于可迭代表中的每个元素,然后返回一个新的可迭代表,其中只包含函数返回 true 值的元素。下面的示例过滤了给定范围内的整数值列表,只返回偶数值:

def is_even(n):
return n%2 == 0
nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_list = filter(is_even, nums_list)
print(list(even_list))

在上面的代码中,首先要定义一个函数 is_even ,用于计算传递给它的偶数。 然后,创建一个包含 1 到 10 之间整数值的列表 nums_list。最后,定义一个新的 list,即 even_list,使用 filter() 函数将用户定义的方法应用于原始列表,并只返回偶数列表元素。结果如下:

[2, 4, 6, 8, 10]

4. Map

filter() 类似,Python 的 map() 函数也将一个可迭代元素和一个函数作为参数。但它不是返回初始可迭代的元素,而是返回一个新的可迭代,其中包含应用到第一个可迭代的每个元素的函数的结果。要对整数列表进行平方,请使用 map() 函数:

my_list = [2, 4, 6, 8, 10]
square_numbers = map(lambda x: x ** 2, my_list)
print(list(square_numbers))

在这段代码中, x 是遍历列表并通过平方计算对其进行转换的迭代器。 map() 函数将原始列表作为参数,与映射函数一起执行该操作。输出结果如下

[4, 16, 36, 64, 100]

5. Sorted

sorted 函数按特定顺序(升序或降序)对给定 iterable 中的元素进行排序,并以列表形式返回。该函数最多可接收 3 个参数: iterablereverse (可选)和 key (可选)。 key 是一个计算值的函数,用于确定 iterable 中元素的排序顺序,默认值为 None。

下面的示例说明了如何在各种可迭代表中应用 sorted 函数:

# set
py_set = {'e', 'a', 'u', 'o', 'i'}
print(sorted(py_set, reverse=True))
# dictionary
py_dict = {'e': 1, 'a': 2, 'u': 3, 'o': 4, 'i': 5}
print(sorted(py_dict, reverse=True))
# frozen set
frozen_set = frozenset(('e', 'a', 'u', 'o', 'i'))
print(sorted(frozen_set, reverse=True))
# string
string = "kinsta"
print(sorted(string))
# list
py_list = ['a', 'e', 'i', 'o', 'u']
print(py_list)

输出结果如下:

['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['a', 'i', 'k', 'n', 's', 't']
['a', 'e', 'i', 'o', 'u']

如何处理迭代表中的边缘情况和错误

边缘情况在许多编程场景中都很常见,你应该在迭代表中预见到它们。让我们来探讨一下可能遇到的几种情况。

1. 空迭代表

当可迭代表为空,但某些编程逻辑试图遍历它时,您可能会遇到问题。你可以通过编程来解决这个问题,以避免效率低下。下面是一个使用 if not 语句检查列表是否为空的示例:

fruits_list=[]
if not fruits_list:
print("The list is empty")

结果就是如此:

The list is empty

2. 嵌套迭代

Python 还支持嵌套迭代,即迭代对象中包含其他迭代对象。例如,您可以有一个食物列表,其中包含嵌套的食物类别列表,如肉类、蔬菜和谷物。下面介绍如何使用嵌套可迭代对象对这种情况进行建模:

food_list = [["kale", "broccoli", "ginger"], ["beef", "chicken", "tuna"], ["barley", "oats", "corn"]]
for inner_list in food_list:
for food in inner_list:
print(food)

在上面的代码中, food_list 变量包含三个嵌套列表,分别代表不同的食物类别。外循环( for inner_list in food_list: )遍历主列表,内循环( for food in inner_list: )遍历每个嵌套列表,打印每个食品项目。输出结果如下

kale
broccoli
ginger
beef
chicken
tuna
barley
oats
corn

3. 异常处理

在 Python 中,迭代表还支持异常处理操作。例如,您可能在遍历一个 list 时遇到 IndexError。这个错误意味着您试图引用的元素超出了可迭代表的边界。下面介绍如何使用 try-except 块来处理这种异常:

fruits_list = ["apple", "mango", "orange", "pear"]
try:
print(fruits_list[5])
except IndexError:
print("The index specified is out of range.")

在上面的代码中, fruits_list 可迭代程序包含五个元素,分别由 list 集合中的索引 05 映射。 try 子句包含一个 print 函数,该函数试图显示迭代器索引 5 处的值,但该值并不存在。这将执行 except 子句,并返回相关的错误信息。控制台返回错误信息:

The index specified is out of range.

小结

掌握 Python 中的迭代对于高效和可读代码至关重要。了解对不同数据结构进行迭代的各种方法、使用理解、生成器以及利用内置函数,能让你成为一名精通 Python 的程序员。

无论是处理列表、字典、字符串还是自定义对象,了解如何使用和操作迭代都是 Python 编程中不可或缺的技能。

评论留言