Python 学习笔记 5:流程控制、循环与迭代器


一、背景

上一篇整理了 Python 中的字符串、列表、元组、集合和字典。

这一篇继续整理 Python 中的流程控制、循环和迭代器。对应的练习代码主要包括:

32循环技巧.py
33分支语句.py
34while循环.py
35range函数.py
36for循环.py
37Break与continue语句.py
38迭代器.py
39生成器.py

这部分内容看起来比较基础,但是实际写程序时非常常用。

比如:

  1. 根据不同条件走不同逻辑
  2. 遍历列表、字典、字符串
  3. 跳过某些不需要处理的数据
  4. 在找到目标数据后提前退出循环
  5. 使用迭代器或生成器按需处理数据

二、if 分支语句

if 用来做条件判断。基本语法如下:

if 条件1:
    代码块1
elif 条件2:
    代码块2
else:
    代码块3

例如:

num = 5

if num == 3:
    print("boss")
elif num == 2:
    print("user")
elif num == 1:
    print("worker")
elif num < 0:
    print("error")
else:
    print("roadman")

这里需要注意几点:

  1. 条件后面要写冒号 :
  2. Python 使用缩进表示代码块
  3. 同一代码块的缩进必须保持一致
  4. if 可以有多个 elif
  5. else 不是必须的

三、Python 中的真假值

在 Python 中,很多对象都可以直接放到条件判断中。

下面这些值会被认为是 False

说明
False 布尔假
None 空值
0 数字 0
"" 空字符串
[] 空列表
{} 空字典
set() 空集合
() 空元组

其他大多数值会被认为是 True

例如:

names = []

if names:
    print("列表中有数据")
else:
    print("列表为空")

这种写法比 if len(names) > 0: 更简洁。

四、多个条件组合

可以使用 andornot 组合多个条件。

1. and

and 表示多个条件都成立。

num = 9

if num >= 0 and num <= 10:
    print("num 在 0 到 10 之间")

也可以写得更符合 Python 风格:

num = 9

if 0 <= num <= 10:
    print("num 在 0 到 10 之间")

2. or

or 表示只要有一个条件成立。

num = 12

if num < 0 or num > 10:
    print("num 不在 0 到 10 之间")

3. not

not 表示取反。

names = []

if not names:
    print("列表为空")

五、Python 没有 switch-case

早期 Python 中没有 switch-case 语句,通常使用 if...elif...else 或字典映射来替代。

例如:

role = "admin"

if role == "admin":
    print("管理员")
elif role == "user":
    print("普通用户")
else:
    print("未知角色")

也可以使用字典映射:

role = "admin"

role_map = {
    "admin": "管理员",
    "user": "普通用户",
    "guest": "访客",
}

print(role_map.get(role, "未知角色"))

如果后续使用的是 Python 3.10 之后的版本,也可以了解 match...case,不过基础阶段先掌握 if...elif...else 更重要。

六、while 循环

while 会在条件成立时重复执行代码。

count = 0

while count < 5:
    print("count =", count)
    count += 1

执行过程是:

  1. 判断 count < 5
  2. 条件成立就执行循环体
  3. 执行完循环体后再次判断条件
  4. 条件不成立时退出循环

while 时要特别注意循环变量的变化,否则很容易写成死循环。

例如下面这种写法会一直运行:

# count = 0
# while count < 5:
#     print(count)

因为 count 没有变化,条件会一直成立。

七、while…else

Python 的循环可以带 else

count = 0

while count < 5:
    print(count, "is less than 5")
    count += 1
else:
    print(count, "is not less than 5")

这里的 else 会在循环正常结束时执行。

如果循环中通过 break 提前退出,else 不会执行。

count = 0

while count < 5:
    if count == 3:
        break
    print(count)
    count += 1
else:
    print("正常结束")

这个例子中,count == 3 时触发 break,所以不会打印 正常结束

八、range 函数

range() 常用于生成一段整数序列。

1. 只指定结束值

for x in range(3):
    print(x)

输出:

0
1
2

range(3) 表示从 03,但是不包含 3

2. 指定开始和结束

for x in range(4, 8):
    print(x)

输出:

4
5
6
7

3. 指定步长

for x in range(0, 30, 5):
    print(x)

输出:

0
5
10
15
20
25

range() 的特点是包前不包后,这一点和切片类似。

九、for 循环

for 循环用于遍历可迭代对象,例如字符串、列表、元组、字典、集合等。

1. 遍历字符串

for letter in "Python":
    print(letter)

2. 遍历列表

fruits = ["banana", "apple", "mango"]

for fruit in fruits:
    print(fruit)

3. 使用 range 遍历索引

fruits = ["banana", "apple", "mango"]

for index in range(len(fruits)):
    print(index, fruits[index])

不过如果既要索引又要值,更推荐使用 enumerate()

fruits = ["banana", "apple", "mango"]

for index, fruit in enumerate(fruits):
    print(index, fruit)

十、循环技巧

练习代码中整理了几个常用循环技巧,这些写法在实际开发中很常见。

1. items 遍历字典

user = {
    "name": "xiaoming",
    "age": 18,
}

for key, value in user.items():
    print(key, value)

2. enumerate 获取索引和值

names = ["xiaoming", "xiaohong", "xiaogang"]

for index, name in enumerate(names):
    print(index, name)

3. zip 同时遍历多个序列

names = ["xiaoming", "xiaohong", "xiaogang"]
ages = [18, 16, 19]

for name, age in zip(names, ages):
    print(name, age)

需要注意:zip() 会按最短的序列结束。

names = ["a", "b", "c"]
ages = [10, 20]

print(list(zip(names, ages)))
# [('a', 10), ('b', 20)]

4. sorted 排序后遍历

nums = [1, 4, 3, 6, 5, 7]

for num in sorted(nums):
    print(num)

如果需要倒序:

for num in sorted(nums, reverse=True):
    print(num)

十一、break 和 continue

breakcontinue 都用于控制循环流程。

语句 含义
break 直接结束整个循环
continue 跳过本次循环,进入下一轮

1. break

for letter in "Python":
    if letter == "h":
        break
    print(letter)

输出:

P
y
t

遇到 h 后,循环直接结束。

2. continue

for letter in "Python":
    if letter == "h":
        continue
    print(letter)

输出:

P
y
t
o
n

遇到 h 后,只是跳过当前这一轮,后面的 on 还会继续处理。

3. 打印 1 到 10 之间的奇数

n = 0

while n < 10:
    n += 1

    if n % 2 == 0:
        continue

    print(n)

这里通过 continue 跳过偶数,只打印奇数。

十二、嵌套循环

循环中还可以再写循环。

例如打印乘法组合:

for i in range(1, 4):
    for j in range(1, 4):
        print(i, "*", j, "=", i * j)

嵌套循环中使用 break 时,只会跳出当前这一层循环。

for i in range(3):
    for j in range(3):
        if j == 1:
            break
        print(i, j)

如果嵌套层级太深,代码会变得难读。这种情况下通常需要考虑拆函数。

十三、迭代器

迭代是 Python 中访问集合元素的一种方式。

迭代器有两个核心特点:

  1. 可以记住当前遍历到的位置
  2. 只能向前取值,不能回退

可以使用 iter() 创建迭代器,使用 next() 取下一个值。

nums = [1, 2, 3, 4]

it = iter(nums)

print(next(it))  # 1
print(next(it))  # 2

当迭代器没有更多元素时,会抛出 StopIteration

nums = [1, 2]
it = iter(nums)

print(next(it))  # 1
print(next(it))  # 2
# print(next(it))  # StopIteration

平时我们很少手动写 next(),更多是让 for 循环自动处理。

nums = [1, 2, 3, 4]

for num in iter(nums):
    print(num)

for 循环内部会不断调用 next(),并在遇到 StopIteration 时结束循环。

十四、自定义迭代器

如果一个类要作为迭代器使用,需要实现两个方法:

  1. __iter__()
  2. __next__()

示例:

class MyNumbers:
    def __iter__(self):
        self.current = 1
        return self

    def __next__(self):
        if self.current <= 5:
            value = self.current
            self.current += 1
            return value

        raise StopIteration


nums = MyNumbers()

for num in nums:
    print(num)

输出:

1
2
3
4
5

这里的关键是:当没有数据可取时,要抛出 StopIteration,告诉 Python 迭代已经结束。

十五、生成器

生成器也是一种迭代器。

相比自己写 __iter__()__next__(),生成器写起来更简单。

1. 生成器表达式

把列表推导式的中括号改成小括号,就得到了生成器表达式。

nums = [2 * x for x in range(3)]
print(nums)
# [0, 2, 4]

gen = (2 * x for x in range(3))

print(next(gen))  # 0
print(next(gen))  # 2
print(next(gen))  # 4

列表推导式会一次性生成完整列表,生成器表达式会按需生成数据。

如果数据量很大,生成器更节省内存。

2. yield 生成器函数

函数中只要出现 yield,这个函数调用后返回的就是一个生成器对象。

def count_up_to(max_num):
    current = 1

    while current <= max_num:
        yield current
        current += 1


for num in count_up_to(5):
    print(num)

输出:

1
2
3
4
5

yieldreturn 不一样。

写法 含义
return 函数直接结束并返回结果
yield 暂停函数,返回一个值,下次继续从暂停位置往下执行

十六、什么时候使用生成器

生成器适合下面这些场景:

  1. 数据量比较大,不想一次性全部加载到内存
  2. 数据是逐条产生的
  3. 只需要遍历一次
  4. 想把数据生产逻辑写得更清楚

例如模拟逐行读取日志:

def read_lines():
    yield "2023-12-09 10:00:00 INFO start"
    yield "2023-12-09 10:00:01 INFO running"
    yield "2023-12-09 10:00:02 INFO end"


for line in read_lines():
    print(line)

后面学习文件读取时,这种思想会经常用到。

十七、总结

这一篇主要整理了流程控制、循环和迭代器。

需要重点记住:

  1. if...elif...else 用来处理分支判断
  2. Python 使用缩进表示代码块
  3. while 适合条件循环,for 适合遍历对象
  4. range() 常用于生成整数序列
  5. break 结束循环,continue 跳过本次循环
  6. enumerate()zip()items() 是非常常用的循环技巧
  7. 迭代器通过 iter()next() 工作
  8. 生成器通过 yield 或生成器表达式按需产生数据

后面写函数、文件处理、JSON 处理和爬虫时,循环和迭代会一直出现。


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录