解释器
python
解释器通常以这几种方式执行代码:
- 直接运行脚本文件(最常见):
python script.py [args]
- 交互模式:命令行输入
python
进入交互模式。 - 以字符串的方式传入:
# 单行代码
python -c "print('Hello, World!')"
# 多行代码(分号分隔)
python -c "import sys; print(sys.version)"
- 以模块的方式执行:
python -m module_name [args]
- 管道:
echo "print(1+1)" | python
基本数据类型
Python
中只有六种基本数据类型:
- int
- float
- complex(复数)
- str
- bool:
True
或False
- NoneType:只有一个值
None
,表示空值或无值。
控制流
顺序结构
代码从上到下逐行执行(这是默认的流程)。
选择结构
if
语句
if condition_1:
# 如果 condition_1 为 True,执行这里的代码
elif condition_2:
# 如果 condition_1 为 False,但 condition_2 为 True,执行这里的代码
else:
# 如果以上所有条件都为 False,执行这里的代码
match
语句(3.10+)
类似于其他语言中的 switch 语句,但功能更强大,提供了“结构化模式匹配”的能力。
支持复杂的模式匹配,不仅匹配值,还能匹配数据结构、类型、甚至解构嵌套对象。
match value:
case [x, y, z]: # 匹配长度为3的列表
print(f"列表: {x}, {y}, {z}")
case {"key": val}: # 匹配字典中的键
print(f"字典值: {val}")
case int(): # 匹配类型
print("这是一个整数")
case _: # 默认情况,相当于其他语言的default
print("未知命令")
还有非常多的高阶用法。
循环结构
for
循环
for 变量 in 可迭代对象:
循环体
通常会结合 range()
生成数字序列,常用于指定循环次数。
for i in range(5): # 0 到 4
print(i)
for i in range(1, 6): # 1 到 5
print(i)
for i in range(0, 10, 2): # 0, 2, 4, 6, 8(步长为2)
print(i)
while
循环
while 条件:
循环体
循环控制语句
break
:立即退出整个循环
for num in [1, 2, 3, 4, 5]:
if num == 3:
break
print(num) # 输出: 1, 2
continue
:跳过当前迭代,进入下一次
for num in [1, 2, 3, 4, 5]:
if num == 3:
continue
print(num) # 输出: 1, 2, 4, 5
else
:循环正常结束后执行(未被break
中断时)
for num in [1, 2, 3]:
print(num)
else:
print("循环完成") # 会执行
for num in [1, 2, 3]:
if num == 2:
break
print(num)
else:
print("不会执行") # 因为被 break 中断
for num in [1, 2, 3]:
if num == 3:
continue
print(num)
else:
print("会执行") # 因为被 break 中断
函数
语法
def function_name(parameter1, parameter2, ...):
"""
这是一个文档字符串 (Docstring),用来描述函数的功能。
"""
# 函数体 (Function Body)
# 在这里执行代码逻辑
return # 可选的返回值
参数
- 位置参数:调用时,实参的顺序必须与定义时参数的顺序一致。
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type} named {pet_name}.")
describe_pet("hamster", "Harry") # "hamster" 对应 animal_type, "Harry" 对应 pet_name
- 关键字参数: 调用时,通过 参数名=值 的形式指定实参,这样就无需关心顺序。
describe_pet(pet_name="Willy", animal_type="whale") # 顺序可以颠倒
- 默认参数: 定义函数时,可以为参数提供一个默认值。如果调用时没有为该参数提供值,就会使用默认值。
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
greet("Alice") # 输出: Hello, Alice! (使用默认 greeting)
greet("Bob", greeting="Hi") # 输出: Hi, Bob! (提供新的 greeting)
- 可变数量的参数: 有时候你无法提前确定函数会接收多少个参数,这时可以使用
*args
和**kwargs
。
args
: 它会将所有多余的位置参数收集到一个元组 (tuple) 中。
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 输出: 6
print(sum_all(10, 20, 30, 40)) # 输出: 100
**kwargs
它会将所有多余的关键字参数收集到一个字典 (dictionary) 中。
def build_profile(first, last, **user_info):
"""创建一个字典,包含我们知道的关于用户的一切。"""
profile = {'first_name': first, 'last_name': last}
profile.update(user_info) # 将 user_info 字典合并到 profile 中
return profile
user_profile = build_profile('albert', 'einstein',
location='princeton',
field='physics')
print(user_profile)
# 输出: {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
Tips
一个函数定义中,参数的常规顺序是: 标准参数 → 默认参数 → *args
→ **kwargs
返回值
函数可以使用 return
语句返回一个或多个值。如果没有 return
语句,函数执行完毕后自动返回 None
。
返回单个值:
def square(number):
return number * number
result = square(4) # result is 16
返回多个值: 实际上,Python 是将多个值打包成一个元组 (tuple) 返回。
def get_user_info():
name = "Alex"
age = 30
return name, age
user_name, user_age = get_user_info() # 这里是元组解包
print(f"Name: {user_name}, Age: {user_age}") # 输出: Name: Alex, Age: 30
info = get_user_info()
print(info) # 输出: ('Alex', 30)
数据结构
列表 (List)
- 定义: 一个有序的、可变的元素集合。
- 特点:
- 有序: 元素按插入的顺序存储,每个元素都有一个固定的索引。
- 可变: 创建后可以随时添加、删除或修改其中的元素。
- **允许重复 **: 可以包含相同的元素。
- **异构性 **: 可以包含不同数据类型的元素(如数字、字符串、甚至其他列表)。
- 适用场景: 当你需要一个会变化的有序集合时,比如存储用户的购物清单、文章的段落等。
- 语法: 使用方括号
[]
定义。
代码示例:
# 创建列表
fruits = ["apple", "banana", "cherry"]
print(f"原始列表: {fruits}")
# 1. 访问元素 (通过索引)
first_fruit = fruits[0] # "apple"
print(f"第一个水果: {first_fruit}")
# 2. 修改元素
fruits[1] = "blackberry"
print(f"修改后: {fruits}") # ['apple', 'blackberry', 'cherry']
# 3. 添加元素
fruits.append("date") # 在末尾添加
print(f"添加后: {fruits}") # ['apple', 'blackberry', 'cherry', 'date']
# 4. 删除元素
fruits.remove("apple") # 删除指定值的元素
popped_fruit = fruits.pop(1) # 删除指定索引的元素并返回它
print(f"删除后: {fruits}") # ['blackberry']
print(f"被弹出的水果: {popped_fruit}") # cherry
元组 (Tuple)
元组可以看作是“不可变的列表”。
- 定义: 一个有序的、不可变的元素集合。
- 特点:
- 有序: 和列表一样,元素有固定顺序和索引。
- 不可变: 一旦创建,就不能添加、删除或修改任何元素。
- 允许重复: 和列表一样,可以包含重复元素。
- 适用场景:
- 当你有一组数据不希望被修改时,例如坐标点
(x, y)
、RGB颜色值(255, 0, 0)
。 - 作为字典的键(因为键必须是不可变的)。
- 从函数返回多个值时,Python 默认会打包成元组。
- 当你有一组数据不希望被修改时,例如坐标点
- 语法: 使用圆括号
()
定义。
代码示例:
# 创建元组
point = (10, 20)
colors = ("red", "green", "blue", "red")
# 1. 访问元素
x_coordinate = point[0]
print(f"X坐标: {x_coordinate}")
# 2. 尝试修改 (会报错!)
try:
point[0] = 15
except TypeError as e:
print(f"修改元组失败: {e}") # TypeError: 'tuple' object does not support item assignment
# 3. 元组解包 (Tuple Unpacking)
name, age, city = ("Alice", 30, "New York")
print(f"姓名: {name}, 年龄: {age}")
字典 (Dictionary)
字典是一种键值对的集合,非常适合用来存储映射关系。
- 定义: 一个无序的(在 Python 3.7+ 版本中是有序的)、可变的键值对集合。
- 特点:
- 键值对: 每个元素都由一个唯一的“键”和一个“值”组成。
- 键唯一且不可变: 字典中的键不能重复,且必须是不可变类型(如字符串、数字、元组)。
- 可变: 可以随时添加、删除或修改键值对。
- 有序性: 从 Python 3.7 开始,字典会记住元素的插入顺序。
- 适用场景: 当你需要通过一个唯一的标识符(键)来查找、存储和更新相关信息时。例如,存储一个用户的个人信息、一本书的属性等。
- 语法: 使用花括号
{}
定义,形式为{key1: value1, key2: value2}
。
代码示例:
# 创建字典
person = {
"name": "Bob",
"age": 25,
"city": "Paris"
}
print(f"原始字典: {person}")
# 1. 访问值 (通过键)
print(f"姓名: {person['name']}")
print(f"年龄: {person.get('age')}") # .get()方法更安全,如果键不存在返回None
# 2. 修改/添加键值对
person["age"] = 26 # 修改已存在的键
person["job"] = "Engineer" # 添加新的键值对
print(f"更新后: {person}")
# 3. 删除键值对
del person["city"]
print(f"删除后: {person}")
# 4. 遍历
for key, value in person.items():
print(f"{key}: {value}")
集合 (Set)
- 定义: 一个无序的、可变的、不含重复元素的集合。
- 特点:
- 无序: 元素没有固定的顺序,你不能通过索引访问它们。
- 不重复: 自动去除所有重复的元素。
- 可变: 可以添加或删除元素。
- 适用场景:
- 去重: 快速去除列表或其他序列中的重复项。
- 成员测试: 快速判断一个元素是否存在于集合中(比列表快得多)。
- 数学运算: 执行交集 (
&
)、并集 (|
)、差集 (-
) 等数学运算。
- 语法: 使用花括号
{}
定义,但注意创建一个空集合必须用set()
,因为{}
会创建一个空字典。
代码示例:
# 创建集合 (重复元素会被自动移除)
numbers = {1, 2, 3, 4, 3, 2}
print(f"原始集合: {numbers}") # {1, 2, 3, 4}
# 1. 添加和删除元素
numbers.add(5)
numbers.remove(2)
print(f"修改后: {numbers}") # {1, 3, 4, 5}
# 2. 成员测试 (非常快)
print(f"3 是否在集合中? {3 in numbers}") # True
# 3. 集合运算
set_a = {1, 2, 3}
set_b = {3, 4, 5}
print(f"并集: {set_a | set_b}") # {1, 2, 3, 4, 5}
print(f"交集: {set_a & set_b}") # {3}
print(f"差集: {set_a - set_b}") # {1, 2}
collections
模块
当内置数据结构无法满足特定需求时,可以从 collections
模块中寻找更专业的工具。
好的,遵照您的要求,以下是关于 Python 错误和异常的介绍,标题从二级标题开始。
异常
异常(Exception) 指的是在程序执行期间发生的错误事件。当 Python 解释器遇到一个它无法处理的情况时“抛出”一个异常。在程序中,如果没有处理异常,程序就会立即崩溃并退出。
基本语法
try:
# 可能出现异常的代码
except ValueError:
# ValueError 的处理逻辑
except ZeroDivisionError:
# ZeroDivisionError 的处理逻辑
except Exception as e:
# 捕获所有其他未预料到的异常,这是一个好习惯
print(f"-> EXCEPTION: 捕获到一个未预料的异常!类型: {type(e).__name__}, 信息: {e}")
else:
# 如果 try 块中没有发生任何异常,则执行此块
print("-> 进入 else 代码块,因为 try 中没有发生任何异常。")
finally:
# 无论是否发生异常,这个块总是最后执行
print("-> 进入 finally 代码块。这是必须执行的清理步骤。")
except
指定的异常类型是抛出的异常本身,或者是它的父类。例如,except Exception
可以捕获 ValueError
。
主动抛出异常:
raise ExceptionType("这里是描述错误信息的字符串")
异常处理机制
每当一个函数被调用,Python 就会在内存中创建一个“栈帧(Stack Frame)”。这个栈帧包含了该函数的局部变量、参数等信息。当一个函数执行完毕并返回时,它的栈帧就会被弹出(pop)。
Example
- main.py 调用 function_A(),function_A 的栈帧被压入(push) 调用栈的顶部。
- function_A() 调用 function_B(),function_B 的栈帧被压入调用栈的顶部。
- function_B() 调用 function_C(),function_C 的栈帧被压入调用栈的顶部。
此时的调用栈看起来像这样(从上到下):
栈顶 → | function_C 的栈帧 |
---|---|
function_A 的栈帧 | |
main.py 的主模块 | |
异常处理过程遵循以下步骤: |
- 异常被抛出: 当一行代码出错(例如 1 / 0)或者被 raise 语句显式抛出时,Python 会创建一个异常对象**。这个对象包含了错误类型、错误信息等。同时,程序的正常执行立即停止。
- 在当前作用域查找
try...except
: Python 首先会在当前函数(也就是调用栈最顶端的那个栈帧)里查找,看抛出异常的代码是否被包裹在一个 try 块中。如果找到了 try 块:Python 会按顺序检查这个 try 块后面跟着的 except 子句。一旦找到匹配的 except 块,异常就被“捕获”了。异常的传递过程到此结束。如果没有找到任何匹配的 except 块,那么这个 try…except 结构就无法处理该异常。 - 调用栈回溯: 如果在当前作用域没有找到能够处理该异常的 try…except 结构,Python 就会做一件事:它会销毁当前的栈帧(即从当前函数退出),然后将异常对象向上层传递,交给调用它的那个函数。这个过程被称为调用栈回溯。Python 会回到上一层函数(调用栈的下一个栈帧),在那个函数中,从它调用下一层函数的那一行代码开始,重复步骤 2 的过程。
- 重复或最终崩溃: 这个“向上层传递并搜寻 except”的过程会一直持续下去,一层一层地回溯调用栈。如果在回溯的任何一层中,找到了能够处理该异常的 except 块,那么异常就被捕获,程序流程恢复正常。如果这个异常一路向上,回溯到了调用栈的最底层(全局作用域),仍然没有被任何 try…except 捕获,那么程序就会终止。Python 解释器会接手这个异常对象,并将异常的完整信息,包括一个叫做“Traceback”的东西,打印到屏幕上。Traceback 就是调用栈在异常发生那一刻的快照,它告诉你异常是如何一层层传递上来的。