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
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 "
任务:
去掉首尾空格;
把 #
替换成「号」;
其余部分全转小写,再把每个单词首字母大写(即 title()
);
最终得到标准地址: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"
任务:
以逗号拆分,得到各字段列表;
取出日期,并切片成年/月/日三部分,用 /
拼回:2025/09/09
;
把商品名与型号用「 - 」连接,形成短描述:MacBook Air-MGN63CH/A
;
计算小计(单价 × 数量),最后按「日期 | 短描述 | 小计」格式用「 | 」拼成新字符串输出。
预期结果: 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 折
任务:
计算实付:unit_price * quantity * discount
;
格式化方式输出一行文字,参考输出:
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]
【课堂小练习】
目标:考察学生对列表追加、扩展与定点插入三种常用修改操作的区分与灵活运用。
任务:
定义一个列表,包含三个元素10
,20
,30
;
在尾部添加一个元素 99
;
在尾部再添加一组元素 [100, 101, 102]
;
在索引 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四种常见删除/清空操作的区分与使用。
任务:
定义一个列表,lst = [‘red’, ‘green’, ‘blue’, ‘green’, ‘yellow’];
按值删除,仅删第一个’green’ ;
用pop(1)取出并打印索引1
的元素及剩余列表;
无参pop()删掉末尾元素,打印该元素及剩余列表;
一键清空整个列表。
要求:每一步完成之后,都需要输出列表的值。
四、改 & 排序
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
【课堂小练习】
目标:考察列表排序、最值获取、成员存在性判断与元素计数等基础操作。
任务:
定义一个列表, lst = [8, 3, 8, 5, 8, 2, 9, 3]
;
原地降序排序;
输出最大值;
判断数字 8 是否存在;
统计数字 8 出现的次数。
要求:每一步完成之后,都需要输出列表的值。
六、综合案例
【综合案例】“班级成绩管理小系统”
你手里有一份某次测验的原始成绩单,请利用列表的各种增删改查、排序、统计操作,一次性完成以下5个子任务(每步必须输出对应结果):
初始化与录入
从空列表开始,依次追加5名同学的成绩:78, 85, 92, 85, 66
。
补录与修正
① 发现漏录一名同学,成绩为88
,请将其插入到索引2的位置;
② 紧接着把92
分同学的成绩改为95
。
去重与排序
① 仅删除第一次出现的85
;
② 将列表原地按升序 排列并输出。
统计查询
① 输出当前最高分;
② 统计85
分在新列表中出现的次数;
③ 判断90
分是否存在于列表中。
清空备份
把处理完的最终列表一次性清空,并输出“列表已清空,长度: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
【课堂小练习 · 字典“增改”案例】
已有字典 book = {'isbn': '978-7-111', 'title': 'Python基础'}
,用直接赋值方式新增价格 price
68 元,并把 title
改为 'Python核心编程'
,打印字典。
对同一字典使用 setdefault
:
① 若 price
已存在则返回其值,否则设为 88;
② 若 author
不存在则新增 '张三'
并返回该值;
依次打印两个操作的返回值及字典。
对同一字典使用 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}
【课堂小练习 · 字典“查询与遍历”案例】
已有字典 product = {'id': 'P1001', 'spec': {'颜色': '蓝色', '尺寸': 'L'}}
,用方括号取出 id
并打印;用 get
取出 price
并打印,若不存在则返回 -1
。
用多级 get
安全方式取出 spec
中 颜色
的值并打印;再尝试取出 重量
并打印,若不存在则返回 '无数据'
。
分别用三种方式遍历 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 安全补录
① setdefault
取 age
(已存在,返回 19 并打印)
② setdefault
补录 hometown = 'Hangzhou'
(新增并打印)
➜ 打印字典(家乡落户)
任务3 期末总评更新
批量 update
合并 {'passed': False, 'rank': 5}
(原 passed
被覆盖)
➜ 打印字典(喜提未通过 & 年级排名)
任务4 快速查询
① 方括号取 id
② get
取 phone
,缺失返回 'unknown'
③ 多级 get
取 scores
内数学成绩,缺失返回 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 个场景
字典键 / 集合元素
列表不能当键,元组可以:
pos = {(120.5, 30.2): "北京"}
函数多返回值
return x, y
实际返回的是一个元组。
并行赋值
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 :
前面所有条件都为假才执行的代码块
整个结构最多只会执行其中一个分支
注:elif
是 else 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
(公里,浮点数)计费,规则如下:
起步价 10 元,含 2 公里;
2–20 公里(含):每公里 1.6 元;
20 公里以上:每公里 2.4 元。
请计算并输出以下三种里程的车费,结果保留到分(2 位小数):
① 1.8 km
② 18.6 km
③ 26.4 km
4.2 循环语句
循环语句的核心作用是:让计算机重复执行某段代码,直到满足特定条件为止。
Python 中有两种主流循环 (while
与 for
)以及配套关键字 (break
/ continue
/ else
)。
1.while 循环
Python 的 while
循环用于重复执行一段代码块,只要条件为真 。它是“条件控制型”循环,不像 for
是“计数控制型”。
基本语法结构
条件表达式 返回布尔值(True
或 False
)。
每次循环开始前都会重新评估条件。
如果条件为 True
,执行循环体;否则退出循环。
示例:打印 1 到 5
1
2
3
4
i = 1
while i <= 5 :
print ( i )
i += 1
控制语句:break
、continue
、else
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.循环控制语句
控制语句:break
、continue
、else
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 次都输错,锁定' )
易错点
else
与 for/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~5)
4.综合练习
【题目 1 】
已知列表 data = [4, -3, -9, 12, 5, 6, 3, 0]
,用 while
循环遍历该列表(遇到 0 即停):
① 若元素值负数,则忽略;
② 当连续两次 出现的数字都能被 3 整除时,立刻输出它们的和并结束程序;
③ 若遍历到 0 时仍未出现上述连续两数,输出“条件未达成”。
要求:必须使用 while
、continue
、break
、else
。
【题目 2】
驿站收到一串包裹重量(克)列表:
1
weights = [ 1200 , - 1 , 580 , 3200 , 2100 , - 2 , 450 ]
负数表示扫描失败,直接跳过;
一旦遇到 > 2000 克 的大件包裹,立即输出其重量并终止分拣;
若全部扫描完都没有大件,输出 "所有包裹均为小件,自动分拣完成"
。
要求: 仅用 一次 for...else
循环实现,必须用 continue
和 break
。
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
小白步骤
def
起头 → 写函数名 → 括号里写参数。
冒号结尾 → 函数体必须缩进。
想返回结果就 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:学生信息录入】
要求 :
自定义函数 add_student
,参数依次为 name
、age
、gender
、city
(默认值为 "北京"
)。
调用函数时,必须指定参数名传入 gender
,其余参数可按位置或指定参数名传入。
函数返回格式化的字符串:"姓名:{name},年龄:{age},性别:{gender},城市:{city}"
。
示例 :
1
2
3
# 调用示例
result = add_student ( "张三" , 18 , gender = "男" )
print ( result ) # 输出:姓名:张三,年龄:18,性别:男,城市:北京
【题目 2:计算订单总价】
要求 :
自定义函数 calculate_total
,参数为 price
、quantity
(默认值为 1)、discount
(默认值为1,表示无折扣,折扣值为 0~1 的小数)。
调用函数时,必须按指定参数名传入 discount
,其余参数可按位置或指定参数名传入。
函数返回折后总价(保留两位小数)。
示例 :
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 \n Python' )
# 读
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(超细拆解)
(因篇幅所限,这里只给“导读” + 完整可跑代码,课堂可逐行打断点)
导读
我们会用 requests
访问豆瓣接口,一次最多 100 条。
返回的是 JSON,字段里混着中文、空格、缺失值,要清洗。
用 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 ())
课后练习
把 params
里的 limit
改成 200,看豆瓣是不是只返 100(接口封顶)。
把排序关键字换成“评分人数”,找“评分人数最多但分数 < 8.0”的奇葩电影。
如果返回 418 “I’m a teapot”,尝试加 cookies
或 time.sleep()
降速。
结语
本章你学会了:
Python 安装、缩进、注释、变量、类型;
字符串、列表、字典、元组、集合的“增删改查”;
条件、循环、函数、模块、文件、异常;
两个小实战:清洗 URL、抓取豆瓣电影。
下一章我们将引入 BeautifulSoup + XPath,真正解析 HTML 网页,把“肉眼可见”的数据统统抓下来!