Python基础语法学习

目录

1 先把环境跑起来

检查项 命令 正常结果 如果报错了怎么办?
Python 有没有装好 python --version Python 3.11.9 之类 提示“不是内部或外部命令”→ 把 Python 加入系统 PATH
pip 能不能用 python -m pip --version pip 24.0 … 提示 upgrade → 照它说的 python -m pip install -U pip
能不能建虚拟环境 python -m venv venv 出现 venv 文件夹 提示缺少 ensurepip → Ubuntu 用 sudo apt install python3-venv

第一个小程序

把下面 3 行新建成 hello.py,双击或者 python hello.py 能跑就行。

1
2
# 文件:hello.py
print("数据采集入门") # 双引号、单引号都行;这句话会在小黑框里出现

拆给你看

  • print() 是 Python 自带的“扩音器”,括号里写什么就往外吐什么。
  • 字符串可以用单引号 ' '、双引号 " "、三引号 ''' ''' 包裹,效果一样。
  • 行首的 # 叫“单行注释”,机器会无视,写给人类看的。
  • 多行注释用三引号 '''""" 包起来,常用来写函数说明书(docstring)。

2 基础语法结构

2.1 代码长什么样才好看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# ① 缩进用 4 个空格,不要 Tab 和空格混用
if True:# 条件为真
	print("缩进 4 空格")# 这句必须缩进,否则报错

# ② 注释写法
# 这是单行注释
'''
这是
多行注释
'''

小白注意 Python 用“缩进”当大括号 { },只要缩进不对就直接报 IndentationError

2.2 变量与数据类型

1
2
3
4
5
6
7
url = "https://example.com" # 字符串 str
page_count = 100# 整数 int,想多大就多大,不会溢出
is_crawling = True# 布尔 bool,只有 True/False 两个值

print(type(url))# <class 'str'>
print(type(page_count)) # <class 'int'>
print(type(is_crawling))# <class 'bool'>

拆给你看

  • 变量名第一次出现时就被“贴”上数据,不需要提前声明。
  • type() 相当于“照妖镜”,能看出变量到底是什么类型。

3 最常用的“容器”——字符串、列表、字典、元组、集合

3.1 字符串(str)

字符串是 Python 里一切文本的“万能容器”:存文字、传信息、拼格式、做清洗,既能当数据,又能当接口,让人与程序、程序与程序之间用“人话”无缝沟通。

一、查:有没有、在哪、多少次

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
s = "hello python, python!"

#  有没有
print('python' in s)         # True

# 2 第一次/最后一次出现的位置
print(s.find('python'))      # 6   (找不到返回 -1)
print(s.index('python'))     # 6   (找不到抛异常)

# 3. 出现次数
print(s.count('python'))     # 2

【课堂小练习】

目标:用 in / find / index / count 快速完成「有无-定位-计数」三连问。

案例 1:邮箱格式快检

原始数据:email = "user.name@example.com"

任务:

  1. 判断是否同时包含 @.
  2. 找出 @ 第一次出现的位置;
  3. 统计 . 在字符串里共出现几次。

二、改:大小写、去垃圾、替换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
s = "  Python  "

#  大小写
print(s.upper())             # '  PYTHON  '
print(s.lower())             # '  python  '
print(s.title())             # '  Python  '   每个单词首字母大写

# 2. 去空格/指定字符
print(s.strip())             # 'Python'   首尾空格全去掉
print(s.lstrip())            # 'Python  ' 只去左边
print(s.rstrip())            # '  Python' 只去右边

# 3. 替换
url = "https://old.com/api"
new = url.replace("old", "new")
print(new)                   # https://new.com/api

【课堂小练习】

目标:用「大小写 + 去空格 + 替换」组合技,一键把「用户手抖输入」变成「标准字段」。

案例1:收货地址标准化

原始数据:addr = " beiJing Old-STREET #8-2-502 "

任务:

  1. 去掉首尾空格;
  2. # 替换成「号」;
  3. 其余部分全转小写,再把每个单词首字母大写(即 title());
  4. 最终得到标准地址:Beijing Old-Street 号8-2-502

要求:不允许手动拼串,必须纯靠字符串方法。


三、切 & 接:split、join、切片

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
csv_line = "Alice,23,USA"

#  字符串 → 列表
lst = csv_line.split(",")
print(lst)                   # ['Alice', '23', 'USA']

# 2. 列表 → 字符串
again = "-".join(lst)
print(again)                 # Alice-23-USA

# 3. 切片(同列表,左闭右开)
date = "2025-08-07"
print(date[:4])              # '2025'
print(date[5:7])             # '08'

# 4. 字符串拼接(使用 + 运算符)
name = lst[0]
age  = lst[1]
country = lst[2]
info = name + " is " + age + " years old, from " + country + "."
print(info)                  # Alice is 23 years old, from USA.

【课堂小练习】

目标:用「 split → join → 切片 」三步法,把“一行杂合数据”拆干净再拼成“想要的样子”。

案例:订单快照格式化

原始数据:order = "20250909,MacBook Air,MGN63CH/A,¥8999,2"

任务:

  1. 以逗号拆分,得到各字段列表;
  2. 取出日期,并切片成年/月/日三部分,用 / 拼回:2025/09/09
  3. 把商品名与型号用「 - 」连接,形成短描述:MacBook Air-MGN63CH/A
  4. 计算小计(单价 × 数量),最后按「日期 | 短描述 | 小计」格式用「 | 」拼成新字符串输出。

预期结果: 2025/09/09 | MacBook Air-MGN63CH/A | ¥17998

要求:全程不允许手动写死任何字段,必须基于 split 结果动态取; 每个任务完成之后,都需要输出变量的值。

四、格式化的 3 种主流写法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
name, age = "Alice", 18

# 1. % 格式化(老派)
print("姓名:%s,年龄:%d" % (name, age))

# 2. format 格式化(中间派)
print("姓名:{},年龄:{}".format(name, age))

# 3. f-string 格式化(最新最推荐)
print(f"姓名:{name},年龄:{age},明年 {age + 1} 岁")

【课堂小练习】

目标:用「% → str.format → f-string」三种写法中的任意一种写法,把「商品单价、数量、折扣」算出的「实付金额」格式化输出。


案例:购物车小票

原始数据:

1
2
3
4
product = "AirPods Pro"
unit_price = 1999
quantity = 2
discount = 0.85          # 8.5 折

任务:

  1. 计算实付:unit_price * quantity * discount
  2. 格式化方式输出一行文字,参考输出:
    1
    
    商品:AirPods Pro,数量:2,实付:3398.30 元

要求:实付保留 2 位小数。

3.2 列表(list)

列表是 Python 的“百变收纳盒”:按序装任何东西,随时增删改排,用一条索引就能瞬间取出,让一堆数据既听话又好找。

一、创建与查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#  1. 字面量直接造
lst1 = [1, 2, 3]

# 2. 空列表 & 追加
lst2 = []
lst2.append('a')          # 末尾加 1 个元素
print(lst2)               # ['a']

# 3. range 转列表
lst3 = list(range(5))     # [0, 1, 2, 3, 4]

# 4. 长度
print(len(lst3))          # 5

二、增:4 种添加方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
lst = [10, 20]

# 1. 尾部加一个元素
lst.append(30)
print(lst)                # [10, 20, 30]

# 2. 尾部加一堆元素(合并)
lst.extend([40, 50])
print(lst)                # [10, 20, 30, 40, 50]

# 3. 指定位置插入
lst.insert(1, 15)         # 索引 1 处插入 15
print(lst)                # [10, 15, 20, 30, 40, 50]

【课堂小练习】

目标:考察学生对列表追加、扩展与定点插入三种常用修改操作的区分与灵活运用。

任务:

  1. 定义一个列表,包含三个元素102030
  2. 在尾部添加一个元素 99
  3. 在尾部再添加一组元素 [100, 101, 102]
  4. 在索引 2 的位置插入一个元素 66

最终应输出:

[10, 20, 66, 30, 99, 100, 101, 102]

三、删:4 种删除方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
lst = ['a', 'b', 'c', 'd', 'e']

# 1. 按值删除,只删第一次出现的
lst.remove('c')
print(lst)                # ['a', 'b', 'd', 'e']

# 2. 按索引弹出,并返回被弹元素
x = lst.pop(1)            # 索引 1
print(x, lst)             # 'b'  ['a', 'd', 'e']

# 3. 默认 pop() 弹末尾
last = lst.pop()
print(last, lst)          # 'e'  ['a', 'd']

# 4. 清空整个列表
lst.clear()
print(lst)                # []

【课堂小练习】

目标:考察列表按值删除、按索引pop、默认pop及clear四种常见删除/清空操作的区分与使用。

任务:

  1. 定义一个列表,lst = [‘red’, ‘green’, ‘blue’, ‘green’, ‘yellow’];
  2. 按值删除,仅删第一个’green’ ;
  3. 用pop(1)取出并打印索引1的元素及剩余列表;
  4. 无参pop()删掉末尾元素,打印该元素及剩余列表;
  5. 一键清空整个列表。

要求:每一步完成之后,都需要输出列表的值。

四、改 & 排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
lst = [3, 1, 4, 1, 5]

# 1. 索引改值
lst[0] = 99
print(lst)                # [99, 1, 4, 1, 5]

# 2. 原地升序
lst.sort()
print(lst)                # [1, 5, 10, 20, 30, 99]

# 3. 原地降序
lst.sort(reverse=True)
print(lst)                # [99, 30, 20, 10, 5, 1]

# 4. 倒序(不管大小)
old = [3, 1, 4]
old.reverse()
print(old)                # [4, 1, 3]

五、查:索引、计数、是否存在

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
lst = ['p', 'y', 't', 'h', 'o', 'n']

# 20. 索引 → 元素
print(lst[0])               # 'p'
print(lst[-1])              # 'n'   倒数第一个

# 21. 元素 → 索引(找不到抛异常)
print(lst.index('t'))       # 2
# print(lst.index('x'))     # ValueError

# 22. 计数
print(lst.count('y'))       # 1

# 23. 是否存在
print('o' in lst)           # True

【课堂小练习】

目标:考察列表排序、最值获取、成员存在性判断与元素计数等基础操作。

任务:

  1. 定义一个列表, lst = [8, 3, 8, 5, 8, 2, 9, 3]
  2. 原地降序排序;
  3. 输出最大值;
  4. 判断数字 8 是否存在;
  5. 统计数字 8 出现的次数。

要求:每一步完成之后,都需要输出列表的值。

六、综合案例

【综合案例】“班级成绩管理小系统”

你手里有一份某次测验的原始成绩单,请利用列表的各种增删改查、排序、统计操作,一次性完成以下5个子任务(每步必须输出对应结果):

  1. 初始化与录入

    从空列表开始,依次追加5名同学的成绩:78, 85, 92, 85, 66

  2. 补录与修正

    ① 发现漏录一名同学,成绩为88,请将其插入到索引2的位置;

    ② 紧接着把92分同学的成绩改为95

  3. 去重与排序

    ① 仅删除第一次出现的85

    ② 将列表原地按升序排列并输出。

  4. 统计查询

    ① 输出当前最高分;

    ② 统计85分在新列表中出现的次数;

    ③ 判断90分是否存在于列表中。

  5. 清空备份

    把处理完的最终列表一次性清空,并输出“列表已清空,长度:X”。

3.3 字典(dict)

字典是 Python 的“查表神器”:把独一无二的“键”当成门牌号,秒查到对应的“值”,让数据有名有姓、一一对应,随时增删改查。

一、创建与查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1. 空字典 & 字面量
d1 = {}
d2 = {'name': 'Alice', 'age': 23}

# 2. dict() 构造器
d3 = dict(name='Bob', age=24)                 # 关键字形式
d4 = dict([('name', 'Cathy'), ('age', 25)])   # 二元组列表

# 3. 长度
print(len(d2))                                # 2

二、增 & 改:键存在就改,不存在就增

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
d = {'name': 'Alice', 'age': 23}

# 4. 直接赋值
d['gender'] = 'female'      # 新增
d['age'] = 24               # 修改
print(d)                    # {'name': 'Alice', 'age': 24, 'gender': 'female'}

# 5. setdefault:没有才新增,并返回最终值
old = d.setdefault('age', 30)      # 已存在,返回 24
new = d.setdefault('city', 'NY')   # 不存在,新增并返回 'NY'
print(d)                             # {'name': 'Alice', 'age': 24, 'gender': 'female', 'city': 'NY'}

# 6. 批量更新(字典合并)
d.update({'city': 'LA', 'email': 'a@.com'})  # 同键覆盖,新键添加
print(d)                                     # city 被改成 LA

【课堂小练习 · 字典“增改”案例】

  1. 已有字典 book = {'isbn': '978-7-111', 'title': 'Python基础'},用直接赋值方式新增价格 price 68 元,并把 title 改为 'Python核心编程',打印字典。

  2. 对同一字典使用 setdefault

    ① 若 price 已存在则返回其值,否则设为 88;

    ② 若 author 不存在则新增 '张三' 并返回该值;

    依次打印两个操作的返回值及字典。

  3. 对同一字典使用 update:一次性合并 {'price': 78, 'publisher': '机械工业'},其中 price 若已存在则覆盖,打印最终字典。

三、查:3 种取法 + 遍历全家桶

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
d = {'name': 'Alice', 'age': 23, 'scores': {'语文': 92, '数学': 98}}

# 7. 方括号取(找不到抛 KeyError)
print(d['name'])  # Alice
# print(d['gender'])  # KeyError: 'gender'

# 8. get 更安全地取,不会报错(可给默认值)
print(d.get('gender'))  # None
print(d.get('gender', 'unknown'))  # unknown
#
# # 9. 多级嵌套安全取
print(d.get('scores').get('语文'))      # 92
print(d.get('scores', {}).get('语文'))      # 92
#
# # 10. 遍历键
d = {'name': 'Alice', 'age': 23, 'scores': {'语文': 92, '数学': 98}}
for k in d:
    print(k, end=' ')       # name age scores
print()
# 和上面的效果一样
for k in d.keys():
    print(k, end=' ')       # name age scores
print()
#
# # 11. 同时遍历键值
# for k, v in d:  # ValueError: too many values to unpack (expected 2)
#     print(k, v)

for k, v in d.items():
    print(k, v)
# name Alice
# age 23
# scores {'语文': 92, '数学': 98}

# # 12. 只遍历值
for v in d.values():
    print(v, end=' ')       # Alice 23 {'语文': 92, '数学': 98}

【课堂小练习 · 字典“查询与遍历”案例】

  1. 已有字典 product = {'id': 'P1001', 'spec': {'颜色': '蓝色', '尺寸': 'L'}},用方括号取出 id 并打印;用 get 取出 price 并打印,若不存在则返回 -1

  2. 用多级 get 安全方式取出 spec颜色 的值并打印;再尝试取出 重量 并打印,若不存在则返回 '无数据'

  3. 分别用三种方式遍历 product

    ① 只遍历所有键并依次打印;

    ② 同时遍历键和值,每行打印 键:值; ③ 只遍历所有值并依次打印。

四、删:pop / clear

1
2
3
4
5
6
7
8
9
d = {'a': 1, 'b': 2, 'c': 3}

# 13. 按键删除并返回值
x = d.pop('b')
print(x, d)                 # 2 {'a': 1, 'c': 3}

# 14. 一键不留
d.clear()
print(d)                    # {}

五、综合案例

【综合案例 · 一份成绩单的“成长轨迹”】


初始空白档案

1
2
3
4
5
6
7
8
report = {
    "id": 2023001,
    "name": "Alice",
    "age": 18,
    "scores": {"语文": 92, "数学": 98, "英语": 88},
    "passed": True,
    "hobbies": ["reading", "swimming", "coding"]
}

任务1 补齐个人信息

① 新增性别 gender = 'F'

② 年龄 +1 → age = 19

③ 英语成绩提至 英语 = 90

➜ 打印字典(第一次“成长”)


任务2 安全补录

setdefaultage(已存在,返回 19 并打印)

setdefault 补录 hometown = 'Hangzhou'(新增并打印)

➜ 打印字典(家乡落户)


任务3 期末总评更新

批量 update 合并 {'passed': False, 'rank': 5}(原 passed 被覆盖)

➜ 打印字典(喜提未通过 & 年级排名)


任务4 快速查询

① 方括号取 id

getphone,缺失返回 'unknown'

③ 多级 getscores 内数学成绩,缺失返回 0

➜ 三个结果空格分隔一行打印


任务5 遍历全家福

① 遍历所有键

② 遍历键值对,格式 key:value

③ 遍历所有值

➜ 各用一行打印,元素间空格分隔


任务6 毕业清档

pop 删除并返回 rank

clear 一键清空整个字典

➜ 先打印 pop 返回值,再打印清空后字典(两行)

小白口诀

字典是“带名字的抽屉”,找东西用钥匙(键),钥匙不存在就 get 给默认,避免报错。

3.4 元组

一句话先记住:元组就是“不能改的列表”,一旦创建,长度、元素都锁死;也正因为“只读”,它才快、才安全,才能当字典/集合的钥匙。


一、创建 & 基本查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 1. 小括号可省,逗号才是灵魂
t1 = (1, 2, 3)
t2 = 1, 2, 3          # 与上一行等价
single = (42,)        # 单元素必须加逗号,否则变成普通数字

# 2. 空元组
empty = ()

# 3. 长度 & 类型
print(len(t1))        # 3
print(type(t1))       # <class 'tuple'>

二、只读操作(能看,不能改)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
t = ('p', 'y', 't', 'h', 'o', 'n')

# 4. 索引 & 切片(和列表一模一样)
print(t[0])           # 'p'
print(t[-1])          # 'n'
print(t[1:4])         # ('y', 't', 'h')

# 5. 查找
print(t.index('t'))   # 2     第一次出现的位置
print(t.count('t'))   # 2     总共出现次数

# 6. 遍历
for ch in t:
    print(ch, end=' ')  # p y t h o n

三、不可改特性演示(会报错)

1
2
3
t = (1, 2, 3)
# t[0] = 10       # TypeError: 'tuple' object does not support item assignment
# t.append(4)     # AttributeError: 没有 append 方法

四、为啥要用元组?3 个场景

  1. 字典键 / 集合元素 列表不能当键,元组可以: pos = {(120.5, 30.2): "北京"}

  2. 函数多返回值 return x, y 实际返回的是一个元组。

  3. 并行赋值 for x, y in points: 拆包遍历,代码更短更快。


3.5 集合

集合是 Python 的“排重+速算”利器:一键去重、毫秒级判断元素是否存在,还能把交集、并集、差集等集合运算变成一行代码,专治重复与关系问题。

一、创建与查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 空集合 & 字面量
s1 = set()                 # 必须用 set(),{} 是空字典
s2 = {1, 2, 3}             # 字面量
lst = [1, 2, 2, 3]
s3 = set(lst)              # 列表去重
print(s3)                  # {1, 2, 3}

# 2. 不可变集合(可当作字典键)
fs = frozenset([4, 5, 6])
print(fs)                  # frozenset({4, 5, 6})

# 3. 长度
print(len(s2))             # 3

二、增:添加元素

1
2
3
4
5
6
7
8
9
s = {1, 2}

# 4. 加一个
s.add(3)
print(s)                   # {1, 2, 3}

# 5. 加一堆(可迭代)
s.update([4, 5], (6, 7))
print(s)                   # {1, 2, 3, 4, 5, 6, 7}

三、删:4 种常用删除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
s = {10, 20, 30, 40}

# 6. 删除指定元素(不存在抛 KeyError)
s.remove(20)
print(s)                   # {10, 30, 40}

# 7. 安全删除(不存在不报错)
s.discard(999)             # 无异常

# 8. 随机弹出一个并返回(集合无顺序)
x = s.pop()
print(x, s)                # 10 {30, 40}  (结果可能不同)

# 9. 一键清空
s.clear()
print(s)                   # set()

四、集合运算:交并差

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 10. 交集 &
print(A & B)               # {3, 4}
print(A.intersection(B))   # 同上

# 11. 并集 |
print(A | B)               # {1, 2, 3, 4, 5, 6}
print(A.union(B))          # 同上

# 12. 差集 -
print(A - B)               # {1, 2}
print(A.difference(B))     # 同上

五、综合案例

【综合案例题:小明的图书标签整理】

小明是一位图书管理员,他手头有两份本周新到馆的图书标签列表,分别来自两个不同的编目系统。每个标签用字符串表示,列表中可能存在重复标签。

列表 A(第一份): ["Python", "算法", "Python", "数据结构", "算法", "数据库"]

列表 B(第二份): ["算法", "机器学习", "数据库", "深度学习", "算法"]

现在他需要你帮忙完成以下任务:

  • 使用集合一次性去除每份列表中的重复标签;
  • 找出两份列表共同拥有的标签(交集);
  • 统计只在第一份列表出现的标签(差集);
  • 把所有去重后的标签合并成一份完整无重复的总标签库(并集);
  • 最后,从总标签库中随机弹出一个标签作为本周推荐标签并打印。

要求:每一步完成之后,都需要输出结果的值。

4 程序控制流——让代码会“拐弯”

4.1 条件语句

一、单分支

单分支:只有一个“如果”,语法:

1
2
3
if 条件:
    条件为真才执行的代码块必须缩进 4 个空格
后续代码继续从这里开始不再受 if 控制

示例:

1
2
3
4
score = 75
if score >= 60:               # 只有一个判断入口
    print("恭喜你,及格了!")   # 条件成立才执行
print("程序结束")             # 不管条件成不成立都会执行

二、双分支

双分支:非此即彼,语法:

1
2
3
4
5
if 条件:
    条件为真执行的代码块
else:
    条件为假执行的代码块
两条分支必走且仅走一条

示例:

1
2
3
4
5
6
score = 55
if score >= 60:
    print("及格")      # 条件为真走这里
else:
    print("不及格")    # 条件为假走这里
print("成绩判断完毕")  # 后续代码

三、多分支

多分支:依次判断多个条件,语法:

1
2
3
4
5
6
7
8
9
if 条件1:
    条件1为真执行的代码块
elif 条件2:
    条件1为假且条件2为真执行的代码块
elif 条件3:
    前两个条件为假且条件3为真执行的代码块
else:
    前面所有条件都为假才执行的代码块
整个结构最多只会执行其中一个分支

注:elifelse if的简写,表示“否则如果”。

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
score = 83
if score >= 90:
    print("优秀")
elif score >= 80:      # 上一个条件已经过滤掉 ≥90
    print("良好")
elif score >= 70:
    print("中等")
elif score >= 60:
    print("及格")
else:
    print("不及格")
print("等级评定完成")

小白注意:判断可以连写:200 <= code < 300 完全合法。

四、综合练习

某市出租车按行驶里程 distance(公里,浮点数)计费,规则如下:

  1. 起步价 10 元,含 2 公里;
  2. 2–20 公里(含):每公里 1.6 元;
  3. 20 公里以上:每公里 2.4 元。

请计算并输出以下三种里程的车费,结果保留到分(2 位小数):

① 1.8 km ② 18.6 km ③ 26.4 km

4.2 循环语句

循环语句的核心作用是:让计算机重复执行某段代码,直到满足特定条件为止。

Python 中有两种主流循环whilefor)以及配套关键字break / continue / else)。


1.while 循环

Python 的 while 循环用于重复执行一段代码块,只要条件为真。它是“条件控制型”循环,不像 for 是“计数控制型”。

基本语法结构

1
2
while 条件表达式:
    循环体
  • 条件表达式 返回布尔值(TrueFalse)。
  • 每次循环开始前都会重新评估条件。
  • 如果条件为 True,执行循环体;否则退出循环。

示例:打印 1 到 5

1
2
3
4
i = 1
while i <= 5:
    print(i)
    i += 1

控制语句:breakcontinueelse

  • break:提前退出整个循环
  • continue:跳过本次迭代,继续下一轮。
  • else:循环正常走完才执行(被 break 就不执行),常用于“查找失败”场景。

示例:break

1
2
3
4
5
6
i = 1              # 初始化计数器
while True:        # 无限循环(需内部用 break 退出)
    print(i)       # 打印当前 i
    if i == 3:     # 当 i 等于 3 时
        break      # 立即跳出整个 while 循环
    i += 1         # 自增,准备下一轮

示例:continue

1
2
3
4
5
6
i = 0                 # 初始化计数器
while i < 5:          # 当 i 小于 5 时继续循环
    i += 1              # 先自增(本次循环 i 从 1 开始)
    if i == 3:          # 如果 i 为 3
        continue        # 跳过本轮剩余语句(不执行下面的 print)
    print(i)            # 输出当前 i 值(3 被跳过)

示例:else

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 在列表里查找第一个 > 100 的数
nums = [23, 45, 78, 99, 88]     # 注意:没有 >100 的数

for n in nums:
    if n > 100:
        print('找到大于 100 的数:', n)
        break                   # 找到就提前跳出
else:
    # 如果 break 没触发,说明全程没找到
    print('扫描结束,列表里没有大于 100 的数')

死循环(慎用)

1
2
while True:
    print("无限循环")

⚠️ 注意:死循环必须配合 break 或外部中断(如 Ctrl+C)退出。


2.for 循环

Python 的 for 循环本质上是一种 “遍历(迭代)循环”,它不会自己去“计数”,而是 逐个取“可迭代对象”里的元素,直到取完为止。

基础语法骨架

可迭代对象:list、tuple、str、bytes、range、dict、set、生成器、自定义迭代器……

  • 目标变量:每次循环从可迭代对象里取出的当前元素,名字随意起。
  • else 块:仅当循环没有被 break 中断时才会运行。

最常用的 6 种遍历模式

场景 代码片段 说明
① 遍历 list / tuple for item in ['a','b','c']: 元素直接拿
② 遍历字符串 for ch in 'hello': 逐个字符
③ 遍历字典键 for k in d:for k in d.keys(): 默认就是键
④ 遍历字典键值对 for k, v in d.items(): 拆包同时拿键值
⑤ 带索引遍历 for idx, item in enumerate(lst): 从 0 开始计数
⑥ 指定区间步长 for i in range(start, stop, step): 半开区间 [start, stop)

示例1:遍历 list / tuple

1
2
3
4
colors = ['red', 'green', 'blue']
for c in colors:
    print(c, end=' ')
# 输出: red green blue 

示例2:遍历字符串(逐字符)

1
2
3
4
word = "Python"
for ch in word:
    print(ch, end='-')
# 输出: P-y-t-h-o-n-

示例3:遍历字典的键

1
2
3
4
scores = {'Tom': 90, 'Lucy': 95}
for name in scores:        # 等价于 scores.keys()
    print(name, end=' ')
# 输出: Tom Lucy 

示例4:遍历字典的键值对

1
2
3
4
scores = {'Tom': 90, 'Lucy': 95}
for name, score in scores.items():
    print(f'{name}:{score}', end=' | ')
# 输出: Tom:90 | Lucy:95 | 

示例5:带索引遍历(enumerate)

1
2
3
4
colors = ['red', 'green', 'blue']
for idx, color in enumerate(colors):
    print(f'{idx}{color}', end='  ')
# 输出: 0→red  1→green  2→blue  

示例6:指定区间与步长(range)

1
2
3
4
# 打印 1~10 内的奇数
for n in range(1, 11, 2):
    print(n, end=' ')
# 输出: 1 3 5 7 9 

3.循环控制语句

控制语句:breakcontinueelse

  • break:提前退出整个循环
  • continue:跳过本次迭代,继续下一轮。
  • else:循环正常走完才执行(被 break 就不执行),常用于“查找失败”场景。

一、break:立刻“跳出整个循环”,语法:

1
2
3
for ... in ...:
    ...
    break          # 遇到即退出 for/while 所在的最内层循环

执行流程图

1
循环体 → 遇到 break → 直接跳到循环块之后的第一条语句

两大典型模板

“找到即停”

1
2
3
4
5
6
# 在列表里找到第一个负数就打印并结束
nums = [3, 7, 0, -5, 9]
for v in nums:
    if v < 0:
        print('第一个负数是', v)
        break        # 后面 -5、9 不再扫描

while 死循环 + break 出口

1
2
3
4
5
6
7
import random
while True:                     # 看似“死循环”
    n = random.randint(1, 10)
    print('roll →', n)
    if n == 6:
        break                   # 掷出 6 点即退场
print('终于掷出 6,收工!')

易错点

  • break 只能跳出一层循环;嵌套多层需要在对应层写 break。
  • if 搭配时一定注意缩进,千万别把 break 写到 if 外。

二、continue:跳过“本轮剩余语句”,直接下一轮,语法:

1
2
3
for ... in ...:
    ...
    continue       # 立即结束本轮,进入“迭代器下一步”

执行流程图

1
循环体 → 遇到 continue → 本轮剩余语句不再执行 → 回到循环头取下一个元素

典型模板——“过滤式”处理

1
2
3
4
5
6
# 只处理正数,负数和 0 直接无视
data = [4, -3, 0, 7, -6, 8]
for x in data:
    if x <= 0:
        continue      # 负数/0 直接跳过
    print('正数:', x)

易错点

while 循环里写 continue 时,务必确保循环变量仍被更新,否则容易变真·死循环:

1
2
3
4
5
6
i = 0
while i < 5:
    if i == 3:
        continue   # 忘写 i += 1 → 永远卡在 3
    print(i)
    i += 1

三、for / while … else:只有“没被 break”时才跑,语法:

1
2
3
4
5
6
7
for 变量 in 可迭代对象:
    ...
    if 某条件:
        break
else:
    # 可迭代对象全部取完、且从未 break,才会进来
    ...

执行流程图

1
2
循环正常结束(迭代器耗尽)→ 执行 else 块  
循环被 break 提前中断 → 跳过 else 块

两大经典场景

“查找失败提示”(最常用)

1
2
3
4
5
6
for n in [2, 4, 6]:
    if n == 5:
        print('找到了')
        break
else:               # 没被 break,说明没找到
    print('列表里没有 5')

“重试超限”

1
2
3
4
5
6
7
for i in range(3):
    pwd = input('密码:')
    if pwd == '123':
        print('正确')
        break
else:               # 3 次都没 break
    print('3 次都输错,锁定')

易错点

elsefor/while 对齐,千万莫缩进到 if 层,否则逻辑全变。


综合示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 需求:在 1~10 中找能被 7 整除的数
#  1. 找到 → 打印并 break
#  2. 偶数 → 跳过(continue)
#  3. 全扫描完都没找到 → else 提示
for n in range(1, 11):
    if n % 2 == 0:
        continue          # 偶数不看
    if n % 7 == 0:
        print('找到奇数且能被 7 整除的数:', n)
        break
else:
    print('扫描结束,没有符合要求的数')

运行结果(仅两种可能):

1
找到奇数且能被 7 整除的数: 7

或(若把范围改成 1~5)

1
扫描结束,没有符合要求的数

4.综合练习

【题目 1 】

已知列表 data = [4, -3, -9, 12, 5, 6, 3, 0],用 while 循环遍历该列表(遇到 0 即停):

① 若元素值负数,则忽略;

② 当连续两次出现的数字都能被 3 整除时,立刻输出它们的和并结束程序;

③ 若遍历到 0 时仍未出现上述连续两数,输出“条件未达成”。

要求:必须使用 whilecontinuebreakelse

【题目 2】

驿站收到一串包裹重量(克)列表:

1
weights = [1200, -1, 580, 3200, 2100, -2, 450]
  • 负数表示扫描失败,直接跳过;
  • 一旦遇到 > 2000 克 的大件包裹,立即输出其重量并终止分拣;
  • 若全部扫描完都没有大件,输出 "所有包裹均为小件,自动分拣完成"

要求: 仅用 一次 for...else 循环实现,必须用 continuebreak

5 函数与模块——把代码“打包”复用

5.1 自定义函数

把“会重复用到的几行代码”取个名字,以后想用时直接喊这个名字,就能一次性跑完——这就是自定义函数。

在 Python 中,自定义函数使用 def 关键字来定义,基本语法如下:

一、基本语法结构

1
2
3
4
def 函数名(参数1, 参数2, ...):
    """文档字符串(可选,用于说明函数功能)"""
    函数体
    return 返回值  # 可选

示例

1
2
3
4
5
6
7
def add(a, b):
    """返回两个数的和"""
    return a + b

# 调用函数
result = add(3, 5)
print(result)  # 输出 8

关键点说明

元素 说明
def 定义函数的关键字
函数名 应符合标识符命名规则(小写+下划线推荐)
参数 可选,支持默认值、可变参数等
return 返回值,若无则返回 None

小白步骤

  1. def 起头 → 写函数名 → 括号里写参数。
  2. 冒号结尾 → 函数体必须缩进。
  3. 想返回结果就 return,不写默认返回 None

二、函数参数的类别

在 Python 中,自定义函数的参数可以分为以下几种主要类别:

1.位置参数

  • 按照参数位置依次传递,调用时必须提供。
  • 是最常见的参数类型。
1
2
3
4
def add(a, b):
    return a + b

add(1, 2)  # 1 对应 a,2 对应 b

2.默认参数

  • 默认参数必须放在非默认参数之后。
  • 参数有默认值,调用时可以不传。
1
2
3
4
5
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")  # 输出:Hello, Alice!
greet("张三", "早上好")  # 早上好, 张三!

3.关键字参数

  • 调用函数时,使用 参数名=值 的形式,顺序不重要。
  • 提高代码可读性。
1
2
3
4
def divide(a, b):
    return a / b

divide(b=4, a=10)  # 顺序无关

三、综合练习

【题目 1:学生信息录入】

要求

  1. 自定义函数 add_student,参数依次为 nameagegendercity(默认值为 "北京")。
  2. 调用函数时,必须指定参数名传入 gender,其余参数可按位置或指定参数名传入。
  3. 函数返回格式化的字符串:"姓名:{name},年龄:{age},性别:{gender},城市:{city}"

示例

1
2
3
# 调用示例
result = add_student("张三", 18, gender="男")
print(result)  # 输出:姓名:张三,年龄:18,性别:男,城市:北京

【题目 2:计算订单总价】

要求

  1. 自定义函数 calculate_total,参数为 pricequantity(默认值为 1)、discount(默认值为1,表示无折扣,折扣值为 0~1 的小数)。
  2. 调用函数时,必须按指定参数名传入 discount,其余参数可按位置或指定参数名传入。
  3. 函数返回折后总价(保留两位小数)。

示例

1
2
3
# 调用示例
total = calculate_total(100, 3, discount=0.8)
print(total)  # 输出:240.00(原价300,打8折)

5.2 模块导入

1
2
3
4
5
6
7
import os, sys, json# 标准库
import requests # 第三方库

# 调用
print(os.getcwd())# 当前文件夹路径
resp = requests.get("https://httpbin.org/get", timeout=5)
print(resp.status_code) # 200

import 顺序口诀

标准库 → 第三方库 → 自己写的库,中间空一行,方便阅读。


6 文件操作——把数据“倒”进硬盘

6.1 文本文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 写
with open('demo.txt', 'w', encoding='utf-8') as f:
f.write('Hello\nPython')

# 读
with open('demo.txt', encoding='utf-8') as f:
text = f.read()
print("整文件读取:", repr(text))

# 逐行读
with open('demo.txt', encoding='utf-8') as f:
for line in f:
print("行内容:", repr(line.rstrip()))

小白必须记住

  • with 会自动关门,即使中途报错也能关,省心。
  • Windows 中文记事本乱码就加 encoding='utf-8-sig'

6.2 CSV 文件

1
2
3
4
5
6
import csv
rows = [('name', 'age'), ('Alice', 18), ('Bob', 20)]

with open('users.csv', 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f)
writer.writerows(rows)

为什么写 newline='' 防止 Windows 每行多出一个空行。

6.3 JSON 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import json
data = {"电影": "流浪地球", "评分": 7.9}

# 写
with open('movie.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)

# 读
with open('movie.json', encoding='utf-8') as f:
back = json.load(f)
print(back)

参数解释

  • ensure_ascii=False 让中文正常出现。
  • indent=2 让文件好看,方便人类肉眼检查。

7 异常处理——让程序“摔倒了”也能爬起来

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

try:
x = int(input("请输入整数:"))
y = 10 / x
except ValueError as e:
logging.error("输入不是整数:%s", e)
except ZeroDivisionError as e:
logging.error("除以 0 啦:%s", e)
else:
logging.info("结果 = %s", y)
finally:
print("无论对错,都会执行 finally")

小白口诀

  • 把“可能出错”的代码放进 try
  • 一个 except 抓一只“妖怪”,抓不到程序就崩溃。
  • 记录日志用 logging,比 print 专业,还能写文件。

8 小实战:把一堆网址清洗完保存成 JSON

任务描述 给你一堆混着 ftp、空格、换行的 url,只要 http/https 的,并保存成 JSON。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#  制造“脏”数据
with open("url_list.txt", "w") as f:
f.write("https://example.com/page1\n")
f.write("https://example.com/page2\n")
f.write("ftp://example.com/page3\n")

# 2. 读 → 清洗 → 保留 http 开头
with open("url_list.txt", encoding="utf-8") as f:
raw_urls = f.read().splitlines()# 自动识别 \n 或 \r\n

valid_urls = [u.strip() for u in raw_urls if u.strip().startswith("http")]
print("有效链接:", valid_urls)

# 3. 保存结果
import json
with open("valid_urls.json", "w", encoding="utf-8") as f:
json.dump(valid_urls, f, ensure_ascii=False, indent=2)

运行后 同级目录出现 valid_urls.json,打开就能看,格式漂亮。


9 综合案例:抓取豆瓣高分电影并保存 CSV(超细拆解)

(因篇幅所限,这里只给“导读” + 完整可跑代码,课堂可逐行打断点)

导读

  1. 我们会用 requests 访问豆瓣接口,一次最多 100 条。
  2. 返回的是 JSON,字段里混着中文、空格、缺失值,要清洗。
  3. pandas 自动转 CSV,Excel 直接双击不乱码。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 安装依赖
# pip install requests pandas -i https://pypi.tuna.tsinghua.edu.cn/simple

import requests, pandas as pd, os, logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")

#  请求配置
url = "https://m.douban.com/rexxar/api/v2/subject/recent_hot/movie"
params = {"limit": 100, "category": "豆瓣高分", "type": "全部", "ck": "tVS3"}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://movie.douban.com/"
}

# 2. 发送请求
resp = requests.get(url, params=params, headers=headers, timeout=10)
resp.raise_for_status()# 非 200 直接抛异常
logging.info("下载完成,状态码:%s", resp.status_code)

# 3. 解析 JSON
data = resp.json()
items = data.get("items", [])
movies = []
for item in items:
card = item.get("card_subtitle", "").split("/")
card = [c.strip() for c in card]
year = card[0] if len(card) > 0 else ""
country = card[1] if len(card) > 1 else ""
genre = card[2] if len(card) > 2 else ""

movies.append({
"电影名称": item.get("title", ""),
"评分": item.get("rating", {}).get("value") or 0,
"评分人数": item.get("rating", {}).get("count") or 0,
"年份": year,
"国家": country,
"类型": genre
})

# 4. 排序 & 保存
movies.sort(key=lambda x: x["评分"], reverse=True)
df = pd.DataFrame(movies)
df["评分"] = df["评分"].astype(float)
output = "douban_top100.csv"
df.to_csv(output, index=False, encoding="utf-8-sig")
logging.info("已保存 %s 部电影到 %s", len(df), output)
print(df.head())

课后练习

  1. params 里的 limit 改成 200,看豆瓣是不是只返 100(接口封顶)。
  2. 把排序关键字换成“评分人数”,找“评分人数最多但分数 < 8.0”的奇葩电影。
  3. 如果返回 418 “I’m a teapot”,尝试加 cookiestime.sleep() 降速。

结语

本章你学会了:

  • Python 安装、缩进、注释、变量、类型;
  • 字符串、列表、字典、元组、集合的“增删改查”;
  • 条件、循环、函数、模块、文件、异常;
  • 两个小实战:清洗 URL、抓取豆瓣电影。

下一章我们将引入 BeautifulSoup + XPath,真正解析 HTML 网页,把“肉眼可见”的数据统统抓下来!

0%