1. Python 是什么?
一句话介绍
Python 是一门简单易学、功能强大的编程语言。它既可以写几行小脚本自动处理文件,也可以开发大型 Web 应用、数据分析系统甚至人工智能程序。
为什么选 Python?
| 特点 | 说明 |
|---|---|
| 简单 | 代码像英语一样好读,用缩进代替花括号 |
| 免费 | 完全开源,随便用 |
| 跨平台 | Windows、macOS、Linux 都能跑 |
| 强大 | 自带"电池"——标准库超丰富 |
| 流行 | 数据科学、Web 开发、自动化、AI 都在用 |
Python 名字的由来
Python 这个名字不是来自蟒蛇,而是来自 BBC 的喜剧 “Monty Python 飞行马戏团”。所以 Python 社区的文档里经常能看到各种 Monty Python 的梗。
2. 安装与运行 Python
2.1 安装 Python
Windows:
- 去 python.org 下载安装包
- 安装时务必勾选 “Add Python to PATH”
- 安装后打开命令提示符(cmd),输入
python --version检查
macOS/Linux:
- 大多数系统已预装 Python 3
- 终端输入
python3 --version检查 - 如果没有,用包管理器安装(如
brew install python或apt install python3)
2.2 两种运行方式
方式一:交互模式(适合试代码)
打开终端输入 python3(或 python),会看到:
Python 3.14 (default, April 4 2024, 09:25:04)
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> 是主提示符,在这里可以直接输入代码,回车立刻看到结果:
>>> 2 + 2
4
>>> print("Hello, World!")
Hello, World!
退出交互模式:按 Ctrl+D(Unix)或 Ctrl+Z(Windows),或输入 quit()
方式二:脚本模式(适合写完整程序)
用文本编辑器写一个文件 hello.py:
print("Hello, World!")
然后在终端运行:
python3 hello.py
3. Python 速览 —— 把 Python 当计算器用
3.1 数字运算
Python 可以直接当计算器用:
>>> 2 + 2
4
>>> 50 - 5 * 6
20
>>> (50 - 5 * 6) / 4
5.0
>>> 8 / 5 # 除法总是返回浮点数
1.6
整数除法(向下取整)和取余:
>>> 17 / 3 # 普通除法
5.666666666666667
>>> 17 // 3 # 向下取整除法(丢弃小数部分)
5
>>> 17 % 3 # 取余数
2
>>> 5 * 3 + 2 # 验证:商 × 除数 + 余数
17
乘方运算:
>>> 5 ** 2 # 5 的平方
25
>>> 2 ** 7 # 2 的 7 次方
128
变量赋值:
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
💡 小技巧:交互模式下,上次的结果会保存在变量
_中>>> tax = 12.5 / 100 >>> price = 100.50 >>> price * tax 12.5625 >>> price + _ # _ 就是上次的结果 12.5625 113.0625
3.2 字符串(文本)
字符串就是用引号括起来的文本:
>>> 'spam eggs' # 单引号
'spam eggs'
>>> "Paris rabbit" # 双引号也一样
'Paris rabbit'
转义字符: 用 \ 表示特殊字符
>>> 'doesn\'t' # 用 \' 转义单引号
"doesn't"
>>> "doesn't" # 或者用双引号就不用转义
"doesn't"
换行符 \n:
>>> s = 'First line.\nSecond line.'
>>> print(s)
First line.
Second line.
原始字符串(忽略转义): 在引号前加 r
>>> print('C:\some\name') # \s 和 \n 被转义了
C:\some
ame
>>> print(r'C:\some\name') # 加 r 就原样输出
C:\some\name
多行字符串: 用三个引号 """...""" 或 '''...'''
>>> print("""\
... Usage: thingy [OPTIONS]
... -h Display help
... -H host Hostname
... """)
Usage: thingy [OPTIONS]
-h Display help
-H host Hostname
字符串拼接和重复:
>>> 3 * 'un' + 'ium' # 重复 + 拼接
'unununium'
>>> 'Py' 'thon' # 相邻字符串自动合并
'Python'
索引(取某个字符):
>>> word = 'Python'
>>> word[0] # 第一个字符(索引从 0 开始)
'P'
>>> word[5] # 第六个字符
'n'
>>> word[-1] # 最后一个字符(负数从右往左数)
'n'
>>> word[-2] # 倒数第二个
'o'
切片(取子串):
>>> word[0:2] # 从索引 0 到 2(不含2)
'Py'
>>> word[2:5] # 从索引 2 到 5(不含5)
'tho'
>>> word[:2] # 从开头到索引2
'Py'
>>> word[4:] # 从索引4到结尾
'on'
>>> word[-2:] # 最后两个字符
'on'
🧠 理解切片:把字符串想象成这样
+---+---+---+---+---+---+ | P | y | t | h | o | n | +---+---+---+---+---+---+ 0 1 2 3 4 5 6 -6 -5 -4 -3 -2 -1
s[:i] + s[i:]永远等于s
字符串长度:
>>> len('supercalifragilisticexpialidocious')
34
⚠️ 注意:字符串是不可变的,不能修改某个字符
>>> word[0] = 'J' TypeError: 'str' object does not support item assignment
3.3 列表 —— 最常用的数据容器
列表用方括号 [] 表示,元素用逗号分隔:
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
列表也支持索引和切片:
>>> squares[0] # 第一个元素
1
>>> squares[-1] # 最后一个
25
>>> squares[-3:] # 最后三个
[9, 16, 25]
列表可以修改(和字符串不同):
>>> cubes = [1, 8, 27, 65, 125] # 65 是错的,应该是 64
>>> cubes[3] = 64 # 直接替换
>>> cubes
[1, 8, 27, 64, 125]
添加元素:
>>> cubes.append(216) # 在末尾添加
>>> cubes
[1, 8, 27, 64, 125, 216]
列表拼接:
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
列表长度:
>>> len([1, 2, 3, 4])
4
嵌套列表:
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0][1] # 取第一个列表的第二个元素
'b'
3.4 第一个真正的程序 —— 斐波那契数列
>>> a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a + b
...
0
1
1
2
3
5
8
新知识点:
- 多重赋值:
a, b = 0, 1同时给两个变量赋值 - while 循环:条件为真时重复执行
- 缩进:Python 用缩进表示代码块(一般用 4 个空格)
- print():输出函数,默认在末尾加换行
>>> i = 256 * 256
>>> print('The value of i is', i)
The value of i is 65536
print() 的 end 参数可以取消换行:
>>> a, b = 0, 1
>>> while a < 1000:
... print(a, end=',')
... a, b = b, a + b
...
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,
4. 控制流 —— 让程序做决策
4.1 if 语句(条件判断)
>>> x = int(input("请输入一个整数: "))
>>> if x < 0:
... x = 0
... print('负数已改为0')
... elif x == 0:
... print('零')
... elif x == 1:
... print('一')
... else:
... print('更多')
要点:
if、elif、else后面要加冒号:elif是else if的缩写,可以有多个else是可选的
4.2 for 循环(遍历序列)
Python 的 for 循环不是数数字的,而是遍历序列中的每个元素:
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
⚠️ 不要在遍历列表时修改它!应该遍历副本:
for user, status in users.copy().items(): if status == 'inactive': del users[user]
4.3 range() 函数(生成数字序列)
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
range 的更多用法:
>>> list(range(5, 10)) # 从 5 到 9
[5, 6, 7, 8, 9]
>>> list(range(0, 10, 3)) # 从 0 到 9,步长为 3
[0, 3, 6, 9]
>>> list(range(-10, -100, -30)) # 负数步长
[-10, -40, -70]
按索引遍历列表:
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
💡 更优雅的方式是用
enumerate(),后面会讲
4.4 break 和 continue
break —— 跳出整个循环:
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(f"{n} = {x} × {n//x}")
... break
...
4 = 2 × 2
6 = 2 × 3
8 = 2 × 4
9 = 3 × 3
continue —— 跳过本次循环的剩余部分,进入下一次:
>>> for num in range(2, 10):
... if num % 2 == 0:
... print(f"偶数: {num}")
... continue
... print(f"奇数: {num}")
...
偶数: 2
奇数: 3
偶数: 4
奇数: 5
偶数: 6
奇数: 7
偶数: 8
奇数: 9
4.5 循环的 else 子句
这是 Python 的一个特色:循环正常结束(没有 break)时,执行 else:
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(n, '=', x, '*', n//x)
... break
... else:
... # 循环到底都没找到因数 → 是质数
... print(n, '是质数')
...
2 是质数
3 是质数
4 = 2 * 2
5 是质数
6 = 2 * 3
7 是质数
8 = 2 * 4
9 = 3 * 3
4.6 pass 语句
pass 什么都不做,只是占个位置:
>>> while True:
... pass # 无限等待(Ctrl+C 中断)
...
>>> class MyEmptyClass:
... pass # 空的类
...
>>> def initlog(*args):
... pass # 还没想好怎么实现
...
4.7 match 语句(Python 3.10+)
类似其他语言的 switch/case,但更强大:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _: # _ 是通配符,匹配任何值
return "Something's wrong"
模式匹配可以解包:
# point 是一个 (x, y) 元组
match point:
case (0, 0):
print("原点")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("不是坐标")
5. 函数 —— 把代码打包复用
5.1 定义和调用函数
用 def 关键字定义函数:
>>> def fib(n):
... """打印小于 n 的斐波那契数列"""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
返回值的函数:
>>> def fib2(n):
... """返回斐波那契数列列表"""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a)
... a, b = b, a+b
... return result
...
>>> f100 = fib2(100)
>>> f100
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
要点:
- 函数体第一行的字符串是文档字符串(docstring)
- 没有
return语句的函数返回None - 函数可以赋值给变量:
f = fib; f(100)
5.2 默认参数
def ask_ok(prompt, retries=4, reminder='请再试一次!'):
while True:
reply = input(prompt)
if reply in {'y', 'ye', 'yes'}:
return True
if reply in {'n', 'no', 'nop', 'nope'}:
return False
retries = retries - 1
if retries < 0:
raise ValueError('无效的用户输入')
print(reminder)
调用方式:
ask_ok('真的要退出吗?') # 只用必选参数
ask_ok('覆盖文件?', 2) # 指定 retries
ask_ok('覆盖文件?', 2, '只能 yes/no') # 全部指定
⚠️ 重要警告:默认参数只计算一次!不要用可变对象(如列表)作为默认值:
# ❌ 错误做法 def f(a, L=[]): L.append(a) return L print(f(1)) # [1] print(f(2)) # [1, 2] ← 共享了同一个列表! # ✅ 正确做法 def f(a, L=None): if L is None: L = [] L.append(a) return L
5.3 关键字参数
调用函数时可以指定参数名:
def parrot(voltage, state='a stiff', action='voom'):
print(f"-- This parrot wouldn't {action}")
print(f"if you put {voltage} volts through it.")
print(f"It's {state}!")
# 各种调用方式
parrot(1000) # 位置参数
parrot(voltage=1000) # 关键字参数
parrot(voltage=1000000, action='VOOOOOM')
parrot(action='VOOOOOM', voltage=1000000) # 顺序不重要
规则: 关键字参数必须在位置参数之后
5.4 任意数量的参数
用 *args 接收任意数量的位置参数(打包成元组):
def write_multiple_items(file, separator, *args):
file.write(separator.join(args))
def concat(*args, sep="/"):
return sep.join(args)
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'
用 **kwargs 接收任意数量的关键字参数(打包成字典):
def cheeseshop(kind, *arguments, **keywords):
print(f"-- 有 {kind} 吗?")
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(f"{kw}: {keywords[kw]}")
cheeseshop("Limburger",
"很稀,先生。",
shopkeeper="Michael Palin",
client="John Cleese")
5.5 解包参数列表
把列表/元组解包成位置参数(用 *):
>>> args = [3, 6]
>>> list(range(*args)) # 相当于 range(3, 6)
[3, 4, 5]
把字典解包成关键字参数(用 **):
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
5.6 Lambda 表达式(匿名函数)
用于写简单的单行函数:
>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
另一个常见用法:作为排序的 key 函数:
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1]) # 按第二个元素排序
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
6. 数据结构 —— 装数据的容器
6.1 列表的更多方法
| 方法 | 作用 |
|---|---|
list.append(x) | 末尾添加元素 |
list.extend(iterable) | 用可迭代对象扩展列表 |
list.insert(i, x) | 在位置 i 插入元素 |
list.remove(x) | 移除第一个值为 x 的元素 |
list.pop([i]) | 移除并返回位置 i 的元素(默认最后一个) |
list.clear() | 清空列表 |
list.index(x[, start[, end]]) | 返回 x 第一次出现的索引 |
list.count(x) | 返回 x 出现的次数 |
list.sort(*, key=None, reverse=False) | 原地排序 |
list.reverse() | 原地反转 |
list.copy() | 返回浅拷贝 |
示例:
>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4) # 从索引4开始找
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'
6.2 用列表实现栈(后进先出)
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
6.3 用 deque 实现队列(先进先出)
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry 来了
>>> queue.popleft() # 最早来的走了
'Eric'
>>> queue.popleft()
'John'
>>> queue
deque(['Michael', 'Terry'])
6.4 列表推导式 —— 创建列表的优雅方式
传统方式:
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
列表推导式(一行搞定):
>>> squares = [x**2 for x in range(10)]
带条件的列表推导式:
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
等价于:
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
更多例子:
>>> vec = [-4, -2, 0, 2, 4]
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
展平嵌套列表:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
6.5 del 语句
按索引删除元素:
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:] # 清空整个列表
>>> a
[]
>>> del a # 删除整个变量
6.6 元组 —— 不可变的序列
元组用逗号创建,通常用圆括号括起来:
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> u = t, (1, 2, 3, 4, 5) # 可以嵌套
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
元组不可修改:
>>> t[0] = 88888
TypeError: 'tuple' object does not support item assignment
创建空元组和单元素元组:
>>> empty = ()
>>> singleton = 'hello', # 注意末尾的逗号!
>>> len(singleton)
1
元组解包:
>>> t = 12345, 54321, 'hello!' # 打包
>>> x, y, z = t # 解包
>>> x
12345
6.7 集合 —— 不重复元素的无序集合
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # 重复项已被移除
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket
True
>>> 'crabgrass' in basket
False
集合运算:
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a - b # 差集:在 a 不在 b
{'r', 'd', 'b'}
>>> a | b # 并集:在 a 或 b
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 交集:同时在 a 和 b
{'a', 'c'}
>>> a ^ b # 对称差:在 a 或 b 但不同时在
{'r', 'd', 'b', 'm', 'z', 'l'}
集合推导式:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
6.8 字典 —— 键值对
字典用键(key)来索引,而不是数字:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> list(tel) # 所有键的列表
['jack', 'guido', 'irv']
>>> sorted(tel) # 排序后的键
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
安全地获取值(避免 KeyError):
>>> print(tel.get('irv')) # 不存在返回 None
None
>>> tel.get('irv', 0) # 不存在返回默认值 0
0
创建字典的多种方式:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> {x: x**2 for x in (2, 4, 6)} # 字典推导式
{2: 4, 4: 16, 6: 36}
>>> dict(sape=4139, guido=4127, jack=4098) # 关键字参数
{'sape': 4139, 'guido': 4127, 'jack': 4098}
6.9 循环技巧
遍历字典的键和值:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave
同时获取索引和值(enumerate):
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
同时遍历多个序列(zip):
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print(f'你的{ q }是什么?是{ a }。')
...
你的name是什么?是lancelot。
你的quest是什么?是the holy grail。
你的favorite color是什么?是blue。
反向遍历(reversed):
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
排序后遍历(sorted):
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)): # 去重后排序
... print(f)
...
apple
banana
orange
pear
7. 模块与包 —— 组织你的代码
7.1 什么是模块?
模块就是一个 .py 文件,里面放着 Python 代码。退出解释器后,之前定义的函数就丢了,但模块可以让你重复使用代码。
创建模块 fibo.py:
# 斐波那契数列模块
def fib(n):
"""打印小于 n 的斐波那契数列"""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n):
"""返回斐波那契数列列表"""
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
导入模块:
>>> import fibo
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
导入特定函数:
>>> from fibo import fib, fib2
>>> fib(500)
给模块起别名:
>>> import fibo as fib
>>> fib.fib(500)
给函数起别名:
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
7.2 模块搜索路径
导入模块时,Python 按以下顺序搜索:
- 内置模块
sys.path中的目录(包括当前目录、PYTHONPATH 环境变量、安装默认目录)
>>> import sys
>>> sys.path
['', '/usr/lib/python3.14', ...]
7.3 以脚本方式运行模块
在模块末尾加上:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
这样这个文件既可以当模块导入,也可以当脚本直接运行:
$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
7.4 dir() 函数 —— 查看模块里有什么
>>> import fibo
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir() # 不加参数列出当前作用域的所有名称
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
7.5 包 —— 模块的集合
包就是一个包含 __init__.py 文件的目录。例如:
sound/ # 顶层包
__init__.py # 初始化 sound 包
formats/ # 文件格式转换子包
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
effects/ # 音效子包
__init__.py
echo.py
surround.py
reverse.py
filters/ # 过滤器子包
__init__.py
equalizer.py
vocoder.py
karaoke.py
导入方式:
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
# 或者
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)
# 或者直接导入函数
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
8. 输入与输出 —— 读写文件
8.1 格式化输出
f-string(推荐,Python 3.6+)
在字符串前加 f,用 { } 嵌入变量或表达式:
>>> year = 2016
>>> event = 'Referendum'
>>> f'Results of the {year} {event}'
'Results of the 2016 Referendum'
>>> import math
>>> print(f'π 的值约等于 {math.pi:.3f}')
π 的值约等于 3.142
对齐和格式化:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
... print(f'{name:10} ==> {phone:10d}')
...
Sjoerd ==> 4127
Jack ==> 4098
Dcab ==> 7678
调试用 =:
>>> bugs = 'roaches'
>>> count = 13
>>> area = 'living room'
>>> print(f'Debugging {bugs=} {count=} {area=}')
Debugging bugs='roaches' count=13 area='living room'
str.format() 方法
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"
>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam
>>> print('This {food} is {adjective}.'.format(
... food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.
格式化表格:
>>> for x in range(1, 11):
... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
8.2 读写文件
打开文件:
f = open('workfile', 'w', encoding="utf-8")
模式说明:
| 模式 | 含义 |
|---|---|
'r' | 只读(默认) |
'w' | 写入(覆盖已有文件) |
'a' | 追加 |
'r+' | 读写 |
'b' | 二进制模式(如 'rb') |
推荐用 with 语句(自动关闭文件):
>>> with open('workfile', encoding="utf-8") as f:
... read_data = f.read()
>>> f.closed
True
读取文件:
f.read() # 读取整个文件
f.readline() # 读取一行
for line in f: # 逐行读取(推荐,高效)
print(line)
list(f) # 读取所有行到列表
f.readlines() # 同上
写入文件:
f.write('This is a test\n') # 返回写入的字符数
文件定位:
f.tell() # 当前位置
f.seek(offset, whence) # 移动位置
# whence: 0=文件开头, 1=当前位置, 2=文件末尾
8.3 JSON 数据
保存结构化数据到文件:
>>> import json
>>> x = [1, 'simple', 'list']
>>> json.dumps(x) # 转为 JSON 字符串
'[1, "simple", "list"]'
# 写入文件
>>> with open('data.json', 'w', encoding='utf-8') as f:
... json.dump(x, f)
# 从文件读取
>>> with open('data.json', 'r', encoding='utf-8') as f:
... x = json.load(f)
9. 错误和异常 —— 程序出错了怎么办
9.1 语法错误
最常见的是漏了冒号、括号不匹配等:
>>> while True print('Hello')
File "<stdin>", line 1
while True print('Hello')
^^^^^
SyntaxError: invalid syntax
9.2 异常
语法正确但运行时出错:
>>> 10 * (1/0)
ZeroDivisionError: division by zero
>>> 4 + spam*3
NameError: name 'spam' is not defined
>>> '2' + 2
TypeError: can only concatenate str (not "int") to str
9.3 处理异常 —— try/except
>>> while True:
... try:
... x = int(input("请输入一个数字: "))
... break
... except ValueError:
... print("无效!再试一次...")
多个 except:
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error:", err)
except ValueError:
print("无法转换为整数")
except Exception as err:
print(f"未知错误: {err=}")
raise # 重新抛出
try-except-else-finally:
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("除以零!")
else:
print("结果是", result)
finally:
print("finally 子句总是执行")
>>> divide(2, 1)
结果是 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
9.4 抛出异常
>>> raise NameError('HiThere')
NameError: HiThere
>>> raise ValueError # 等价于 raise ValueError()
重新抛出异常:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('捕获到了!')
... raise # 重新抛出
...
捕获到了!
NameError: HiThere
9.5 自定义异常
class MyError(Exception):
def __init__(self, message):
self.message = message
raise MyError("出错了!")
10. 类 —— 面向对象编程
10.1 最简单的类
class MyClass:
"""一个简单的示例类"""
i = 12345
def f(self):
return 'hello world'
使用类:
>>> MyClass.i # 访问类属性
12345
>>> x = MyClass() # 创建实例
>>> x.f() # 调用方法
'hello world'
10.2 __init__ 方法(构造函数)
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
10.3 类变量 vs 实例变量
class Dog:
kind = 'canine' # 类变量(所有实例共享)
def __init__(self, name):
self.name = name # 实例变量(每个实例独有)
self.tricks = [] # 注意:可变对象要放在实例变量里
def add_trick(self, trick):
self.tricks.append(trick)
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # 共享
'canine'
>>> e.kind # 共享
'canine'
>>> d.name # 独有
'Fido'
>>> e.name # 独有
'Buddy'
10.4 继承
class Animal:
def speak(self):
print("...")
class Dog(Animal):
def speak(self):
print("汪汪!")
class Cat(Animal):
def speak(self):
print("喵喵!")
多重继承:
class DerivedClassName(Base1, Base2, Base3):
pass
10.5 迭代器
让一个类支持 for 循环:
class Reverse:
"""反向遍历序列的迭代器"""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> for char in rev:
... print(char)
...
m
a
p
s
10.6 生成器 —— 更简单的迭代器
用 yield 关键字:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
生成器表达式:
>>> sum(i*i for i in range(10)) # 平方和
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # 点积
260
11. 标准库概览 —— Python 自带的工具箱
11.1 操作系统接口(os)
>>> import os
>>> os.getcwd() # 当前工作目录
'/home/user'
>>> os.chdir('/tmp') # 切换目录
>>> os.system('ls') # 执行系统命令
0
高级文件操作(shutil):
>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
'archive.db'
>>> shutil.move('/build/executables', 'installdir')
'installdir'
11.2 文件通配符(glob)
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']
11.3 命令行参数(sys.argv + argparse)
import sys
print(sys.argv) # ['demo.py', 'one', 'two', 'three']
更专业的 argparse:
import argparse
parser = argparse.ArgumentParser(prog='top')
parser.add_argument('filenames', nargs='+')
parser.add_argument('-l', '--lines', type=int, default=10)
args = parser.parse_args()
print(args)
11.4 正则表达式(re)
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
11.5 数学(math、random、statistics)
>>> import math
>>> math.cos(math.pi / 4)
0.7071067811865476
>>> math.log(1024, 2)
10.0
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10)
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random()
0.17970987693706186
>>> import statistics
>>> statistics.mean([2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5])
1.6071428571428572
11.6 互联网访问
>>> from urllib.request import urlopen
>>> with urlopen('https://docs.python.org/3/') as response:
... for line in response:
... line = line.decode()
... if 'Python' in line:
... print(line.rstrip())
11.7 日期和时间
>>> import datetime as dt
>>> now = dt.date.today()
>>> now
datetime.date(2026, 6, 16)
>>> now.strftime("%Y-%m-%d")
'2026-06-16'
>>> birthday = dt.date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
22613
11.8 数据压缩
>>> import zlib
>>> s = b'witch which has which witches wrist watch'
>>> len(s)
41
>>> t = zlib.compress(s)
>>> len(t)
37
>>> zlib.decompress(t)
b'witch which has which witches wrist watch'
11.9 性能测量(timeit)
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.5753582862602458
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.5496253708577079
11.10 测试(doctest + unittest)
doctest —— 把测试写在文档里:
def average(values):
"""计算数字列表的算术平均值
>>> print(average([20, 30, 70]))
40.0
"""
return sum(values) / len(values)
import doctest
doctest.testmod() # 自动验证
unittest —— 更正式的测试:
import unittest
class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 40.0)
with self.assertRaises(ZeroDivisionError):
average([])
unittest.main()
11.11 更多内置模块
| 模块 | 用途 |
|---|---|
json | JSON 数据解析 |
csv | CSV 文件读写 |
sqlite3 | SQLite 数据库 |
xml.etree.ElementTree | XML 处理 |
email | 邮件处理 |
gettext | 国际化 |
321

被折叠的 条评论
为什么被折叠?



