🐍Python+AI零基础入门
一、Python基础
一、Python 数据存储基础
1.1 变量与对象
| 概念 | 说明 | 示例 |
|---|---|---|
| 变量 | 指向内存中对象的"标签" | a = 10 |
| 对象 | 存储在内存中的数据实体 | 10(整数对象) |
| 引用 | 变量通过引用指向对象 | a 指向 10 |
| 垃圾回收 | 没有引用时自动回收 | 使用 del a 可手动删除引用 |
# 变量赋值本质是创建引用 a = 10 # a 指向 10 b = a # b 也指向 10(同一个对象) print(id(a)) # 输出 a 的内存地址 print(id(b)) # 输出 b 的内存地址(与 a 相同)
1.2 可变 vs 不可变类型
| 类型 | 是否可变 | 示例 |
|---|---|---|
| 不可变类型 | ❌ 不能修改 | int, float, str, tuple, frozenset |
| 可变类型 | ✅ 可以修改 | list, dict, set, bytearray |
# 不可变类型:修改会创建新对象 s = "hello" s = s + " world" # 创建新字符串,原对象被回收 # 可变类型:修改不会创建新对象 lst = [1, 2, 3] lst.append(4) # 在原列表上修改 print(lst) # [1, 2, 3, 4]
二、运算符
2.1 算数运算符
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
+ |
加法 / 拼接 | 3 + 2 "a"+"b" |
5 "ab" |
- |
减法 | 5 - 3 |
2 |
* |
乘法 / 重复 | 3 * 4 "a"*3 |
12 "aaa" |
/ |
除法(浮点数) | 10 / 3 |
3.333... |
// |
整除(向下取整) | 10 // 3 |
3 |
% |
取余(模运算) | 10 % 3 |
1 |
** |
幂运算 | 2 ** 3 |
8 |
# 复合赋值运算符 a = 10 a += 5 # 等价于 a = a + 5 a -= 3 # 等价于 a = a - 3 a *= 2 # 等价于 a = a * 2 a /= 4 # 等价于 a = a / 4 a //= 2 # 等价于 a = a // 2 a %= 3 # 等价于 a = a % 3 a **= 2 # 等价于 a = a ** 2
2.2 比较运算符(返回布尔值)
| 运算符 | 含义 | 示例 |
|---|---|---|
== |
等于 | 3 == 3 → True |
!= |
不等于 | 3 != 4 → True |
> |
大于 | 5 > 3 → True |
< |
小于 | 3 < 5 → True |
>= |
大于等于 | 5 >= 5 → True |
<= |
小于等于 | 3 <= 5 → True |
# 字符串比较(按字典序)
print("apple" < "banana") # True
print("Hello" == "hello") # False(大小写敏感)
2.3 逻辑运算符
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
and |
逻辑与(两者都为 True) | True and False |
False |
or |
逻辑或(至少一个为 True) | True or False |
True |
not |
逻辑非(取反) | not True |
False |
a, b = 5, 10
print(a > 0 and b > 5) # True
print(a > 10 or b > 5) # True
print(not (a > 10)) # True
# 短路运算:逻辑运算会在确定结果时停止
def test():
print("被调用了")
return True
print(False and test()) # 不会调用 test()(短路)
print(True or test()) # 不会调用 test()(短路)
2.3 逻辑运算符
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
and |
逻辑与(两者都为 True) | True and False |
False |
or |
逻辑或(至少一个为 True) | True or False |
True |
not |
逻辑非(取反) | not True |
False |
a, b = 5, 10
print(a > 0 and b > 5) # True
print(a > 10 or b > 5) # True
print(not (a > 10)) # True
# 短路运算:逻辑运算会在确定结果时停止
def test():
print("被调用了")
return True
print(False and test()) # 不会调用 test()(短路)
print(True or test()) # 不会调用 test()(短路)
2.4 成员运算符
| 运算符 | 含义 | 示例 |
|---|---|---|
in |
判断元素是否在序列中 | 3 in [1, 2, 3] → True |
not in |
判断元素是否不在序列中 | 4 not in [1, 2, 3] → True |
2.5 身份运算符
| 运算符 | 含义 | 示例 |
|---|---|---|
is |
判断两个变量是否指向同一对象 | a is b |
is not |
判断两个变量是否指向不同对象 | a is not b |
a = [1, 2, 3] b = [1, 2, 3] c = a print(a == b) # True(值相等) print(a is b) # False(不同对象) print(a is c) # True(同一对象)
2.6 运算符优先级(从高到低)
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1 | () |
括号(最高优先级) |
| 2 | ** |
幂运算 |
| 3 | *, /, //, % |
乘除取余 |
| 4 | +, - |
加减 |
| 5 | ==, !=, >, <, >=, <= |
比较运算符 |
| 6 | not |
逻辑非 |
| 7 | and |
逻辑与 |
| 8 | or |
逻辑或(最低优先级) |
# 建议使用括号提高可读性 result = (2 + 3) * 4 ** 2 # 5 * 16 = 80
三、常用内置函数
3.1 数值运算函数
| 函数 | 说明 | 示例 |
|---|---|---|
abs(x) |
绝对值 | abs(-5) → 5 |
pow(x, y) |
幂运算 | pow(2, 3) → 8 |
round(x, n) |
四舍五入,保留 n 位小数 | round(3.14159, 2) → 3.14 |
max(iterable) |
最大值 | max([1, 5, 3]) → 5 |
min(iterable) |
最小值 | min([1, 5, 3]) → 1 |
sum(iterable) |
求和 | sum([1, 2, 3]) → 6 |
len(iterable) |
长度/元素个数 | len("hello") → 5 |
type(obj) |
获取对象类型 | type(10) → <class 'int'> |
id(obj) |
获取对象内存地址 | id(a) → 140736123456 |
3.2 类型转换函数
| 函数 | 说明 | 示例 |
|---|---|---|
int(x) |
转换为整数 | int("123") → 123 |
float(x) |
转换为浮点数 | float("3.14") → 3.14 |
str(x) |
转换为字符串 | str(123) → "123" |
bool(x) |
转换为布尔值 | bool(0) → False |
list(iterable) |
转换为列表 | list("abc") → ['a','b','c'] |
tuple(iterable) |
转换为元组 | tuple([1,2,3]) → (1,2,3) |
set(iterable) |
转换为集合(去重) | set([1,2,2,3]) → {1,2,3} |
dict(iterable) |
转换为字典 | dict([('a',1)]) → {'a':1} |
3.3 输入输出函数
| 函数 | 说明 | 示例 |
|---|---|---|
print(*objects) |
打印输出 | print("Hello", 123) |
input(prompt) |
获取用户输入(返回字符串) | name = input("请输入:") |
# print 高级用法
print("a", "b", "c", sep="-") # a-b-c
print("Hello", end=" ") # 不换行
print("World") # Hello World
四、字符串运算
| 运算符/方法 | 说明 | 示例 |
|---|---|---|
+ |
字符串拼接 | "Hello" + " World" → "Hello World" |
* |
字符串重复 | "Ha" * 3 → "HaHaHa" |
in |
检查子串 | "he" in "hello" → True |
[] |
索引访问 | "hello"[1] → "e" |
[:] |
切片 | "hello"[1:4] → "ell" |
len() |
获取长度 | len("hello") → 5 |
五、列表运算
| 运算符/方法 | 说明 | 示例 |
|---|---|---|
+ |
列表拼接 | [1,2] + [3,4] → [1,2,3,4] |
* |
列表重复 | [1,2] * 3 → [1,2,1,2,1,2] |
in |
检查元素 | 3 in [1,2,3] → True |
[] |
索引访问 | [1,2,3][1] → 2 |
[:] |
切片(返回新列表) | [1,2,3,4][1:3] → [2,3] |
len() |
获取长度 | len([1,2,3]) → 3 |
max()/min() |
最大/最小值 | max([1,5,3]) → 5 |
sum() |
求和(元素必须为数字) | sum([1,2,3]) → 6 |
六、集合运算(集合特有)
| 运算符 | 含义 | 方法 | 示例 |
|---|---|---|---|
& |
交集 | intersection() |
{1,2,3} & {2,3,4} → {2,3} |
| |
并集 | union() |
{1,2,3} | {3,4,5} → {1,2,3,4,5} |
- |
差集 | difference() |
{1,2,3} - {2,3} → {1} |
^ |
对称差集 | symmetric_difference() |
{1,2,3} ^ {3,4} → {1,2,4} |
<= |
子集 | issubset() |
{1,2} <= {1,2,3} → True |
>= |
超集 | issuperset() |
{1,2,3} >= {1,2} → True |
七、字典运算
| 运算符/方法 | 说明 | 示例 |
|---|---|---|
in |
检查键是否存在 | "name" in d → True |
d[key] |
访问值(键不存在报错) | d["name"] → "张三" |
d.get(key, default) |
安全访问(不存在返回默认值) | d.get("age", 0) → 25 |
d[key] = value |
添加或修改键值对 | d["city"] = "北京" |
del d[key] |
删除键值对 | del d["age"] |
len(d) |
获取键值对数量 | len(d) → 2 |
| (3.9+) |
合并字典 | d1 | d2 |
八、数据存储与运算对比总结表
| 数据类型 | 可变性 | 有序性 | 索引 | 切片 | 加法运算 | 乘法运算 | in 操作 |
|---|---|---|---|---|---|---|---|
| 列表 list | ✅ 可变 | ✅ 有序 | ✅ | ✅ | ✅ 拼接 | ✅ 重复 | ✅ 检查元素 |
| 字符串 str | ❌ 不可变 | ✅ 有序 | ✅ | ✅ | ✅ 拼接 | ✅ 重复 | ✅ 检查子串 |
| 元组 tuple | ❌ 不可变 | ✅ 有序 | ✅ | ✅ | ✅ 拼接 | ✅ 重复 | ✅ 检查元素 |
| 集合 set | ✅ 可变 | ❌ 无序 | ❌ | ❌ | ❌ | ❌ | ✅ 检查元素 |
| 字典 dict | ✅ 可变 | ✅ 有序(3.7+) | ❌(用键访问) | ❌ | ❌ | ❌ | ✅ 检查键 |
九、内存管理要点
| 概念 | 说明 |
|---|---|
| 引用计数 | 每个对象记录被引用的次数,归零时回收 |
| 垃圾回收 | Python 自动回收不再使用的内存 |
| 小整数池 | -5 到 256 的整数在 Python 启动时预先创建,所有变量共享同一对象 |
| 字符串驻留 | 某些字符串会被缓存以节省内存 |
| 深浅拷贝 | 浅拷贝只复制顶层,深拷贝递归复制所有层级 |
# 小整数池示例 a = 10 b = 10 print(a is b) # True(指向同一对象) c = 257 d = 257 print(c is d) # False(超出小整数池,创建了新对象) # 浅拷贝 vs 深拷贝 import copy lst1 = [[1, 2], [3, 4]] lst2 = lst1.copy() # 浅拷贝 lst3 = copy.deepcopy(lst1) # 深拷贝 lst1[0][0] = 999 print(lst2) # [[999, 2], [3, 4]](浅拷贝受影响) print(lst3) # [[1, 2], [3, 4]](深拷贝不受影响)
十、运算符总结表
| 类型 | 运算符 | 说明 |
|---|---|---|
| 算术 | + - * / // % ** |
数学运算 |
| 比较 | == != > < >= <= |
返回布尔值 |
| 逻辑 | and or not |
布尔逻辑 |
| 成员 | in not in |
检查元素是否存在 |
| 身份 | is is not |
检查对象身份(内存地址) |
| 位运算 | & | ^ ~ << >> |
二进制位操作(不常用) |
| 赋值 | = += -= *= /= //= %= **= |
赋值操作 |
二、Python数据容器
一、列表(list)
特点:有序、可变、可重复、支持索引
1.1 创建列表
# 空列表
lst1 = []
lst2 = list()
# 带元素
lst3 = [1, 2, 3, 4, 5]
lst4 = ["a", "b", "c"]
lst5 = [1, "hello", 3.14, True] # 混合类型
lst6 = list("hello") # ['h', 'e', 'l', 'l', 'o']
# 列表推导式
lst7 = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
1.2 增删改查
lst = [1, 2, 3, 4, 5] # 查(索引和切片) print(lst[0]) # 1(索引从0开始) print(lst[-1]) # 5(倒数第一个) print(lst[1:4]) # [2, 3, 4](切片,左闭右开) print(lst[::2]) # [1, 3, 5](步长) # 增 lst.append(6) # [1, 2, 3, 4, 5, 6](末尾添加) lst.insert(0, 0) # [0, 1, 2, 3, 4, 5, 6](指定位置插入) lst.extend([7, 8]) # [0, 1, 2, 3, 4, 5, 6, 7, 8](合并列表) # 改 lst[0] = 100 # [100, 1, 2, 3, 4, 5, 6, 7, 8] # 删 lst.remove(100) # 移除指定元素 lst.pop() # 移除并返回最后一个元素 lst.pop(0) # 移除并返回指定位置元素 del lst[0] # 删除指定位置元素 lst.clear() # 清空列表
二、字符串(str)
特点:有序、不可变、可索引
2.1 创建字符串
s1 = "hello" s2 = 'world' s3 = """多行 字符串""" s4 = str(123) # "123" s5 = " ".join(["a", "b", "c"]) # "a b c"
2.2 查(索引和切片)
s = "Hello World" print(s[0]) # H print(s[-1]) # d print(s[1:4]) # ell print(s[::2]) # HloWrd print(s[::-1]) # dlroW olleH(反转)
2.3 常用方法
s = " Hello World "
# 大小写转换
print(s.lower()) # " hello world "
print(s.upper()) # " HELLO WORLD "
print(s.title()) # " Hello World "
print(s.swapcase()) # " hELLO wORLD "
# 去除空白
print(s.strip()) # "Hello World"(去除两端)
print(s.lstrip()) # "Hello World "(去除左端)
print(s.rstrip()) # " Hello World"(去除右端)
# 查找和替换
print(s.find("World")) # 7(返回索引,找不到返回-1)
print(s.index("World")) # 7(找不到报错)
print(s.count("l")) # 3
print(s.replace("World", "Python")) # " Hello Python "
# 分割和拼接
print("a,b,c".split(",")) # ['a', 'b', 'c']
print("a b c".split()) # ['a', 'b', 'c']
print("-".join(["a", "b"])) # "a-b"
# 判断方法
print(s.isalnum()) # False(包含空格)
print(s.isalpha()) # False(包含空格)
print(s.isdigit()) # False
print("123".isdigit()) # True
print("hello".startswith("he")) # True
print("hello".endswith("lo")) # True
# 填充和对齐
print("5".zfill(3)) # "005"
print("abc".center(10)) # " abc "
print("abc".ljust(10)) # "abc "
print("abc".rjust(10)) # " abc"
三、元组(tuple)
特点:有序、不可变、可重复
2.1 创建元组
t1 = () # 空元组 t2 = (1,) # 单个元素(必须加逗号) t3 = (1, 2, 3, 4, 5) t4 = tuple([1, 2, 3]) # (1, 2, 3) t5 = 1, 2, 3 # (1, 2, 3)(省略括号)
2.2 查(索引和切片)
t = (1, 2, 3, 4, 5) print(t[0]) # 1 print(t[-1]) # 5 print(t[1:4]) # (2, 3, 4) print(len(t)) # 5 print(max(t)) # 5 print(min(t)) # 1 print(sum(t)) # 15 print(t.index(3)) # 2 print(t.count(2)) # 1
2.3 元组的不可变性
t = (1, 2, 3) # t[0] = 100 # ❌ 报错!元组不可变 # 修改元组需要创建新元组 t = t + (4, 5) # (1, 2, 3, 4, 5) t = t * 2 # (1, 2, 3, 4, 5, 1, 2, 3, 4, 5) # 元组解包 a, b, c = (1, 2, 3) # a=1, b=2, c=3
四、集合(set)
特点:无序、可变、元素唯一
4.1. 创建集合
s1 = set() # 空集合(注意:{} 是空字典)
s2 = {1, 2, 3, 4, 5}
s3 = set([1, 2, 2, 3]) # {1, 2, 3}(自动去重)
s4 = set("hello") # {'h', 'e', 'l', 'o'}(顺序不确定)
4.2 增删改查
s = {1, 2, 3}
# 增
s.add(4) # {1, 2, 3, 4}
s.update([5, 6]) # {1, 2, 3, 4, 5, 6}
# 删
s.remove(3) # 移除3,不存在报错
s.discard(10) # 移除10,不存在不报错
s.pop() # 随机移除并返回一个元素
s.clear() # 清空集合
# 查(集合不能通过索引访问,只能遍历)
for item in s:
print(item)
4.3 集合计算
s1 = {1, 2, 3, 4}
s2 = {3, 4, 5, 6}
# 交集
print(s1 & s2) # {3, 4}
print(s1.intersection(s2)) # {3, 4}
# 并集
print(s1 | s2) # {1, 2, 3, 4, 5, 6}
print(s1.union(s2)) # {1, 2, 3, 4, 5, 6}
# 差集
print(s1 - s2) # {1, 2}
print(s1.difference(s2)) # {1, 2}
print(s2 - s1) # {5, 6}
# 对称差集
print(s1 ^ s2) # {1, 2, 5, 6}
print(s1.symmetric_difference(s2)) # {1, 2, 5, 6}
# 子集和超集
print({1, 2}.issubset(s1)) # True
print(s1.issuperset({1, 2})) # True
print(s1.isdisjoint({5, 6})) # False(有交集)
五、字典(dict)
特点:无序(Python 3.7+ 有序)、可变、键值对、键唯一
5.1. 创建字典
# 空字典
d1 = {}
d2 = dict()
# 带元素
d3 = {"name": "张三", "age": 25, "city": "北京"}
d4 = dict(name="张三", age=25, city="北京")
d5 = dict([("name", "张三"), ("age", 25)]) # 从列表创建
# 字典推导式
d6 = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
5.2 增删改查
d = {"name": "张三", "age": 25}
# 查
print(d["name"]) # 张三(键存在)
print(d.get("city")) # None(键不存在返回None)
print(d.get("city", "未知")) # "未知"(自定义默认值)
print(d.keys()) # dict_keys(['name', 'age'])
print(d.values()) # dict_values(['张三', 25])
print(d.items()) # dict_items([('name', '张三'), ('age', 25)])
# 增和改
d["city"] = "北京" # 新增键值对
d["age"] = 26 # 修改已有键的值
d.update({"gender": "男", "age": 27}) # 批量更新
# 删
del d["gender"] # 删除指定键
age = d.pop("age") # 删除并返回指定键的值
item = d.popitem() # 删除并返回最后一个键值对
d.clear() # 清空字典
5.3 遍历字典
d = {"name": "张三", "age": 25, "city": "北京"}
# 遍历键
for key in d:
print(key, d[key])
# 遍历键值对
for key, value in d.items():
print(key, value)
# 遍历值
for value in d.values():
print(value)
5.4 其他常用操作
d = {"name": "张三", "age": 25}
print(len(d)) # 2
print("name" in d) # True(检查键是否存在)
print("gender" in d) # False
# 合并字典(Python 3.9+)
d1 = {"a": 1, "b": 2}
d2 = {"c": 3, "d": 4}
merged = {**d1, **d2} # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# merged = d1 | d2 # Python 3.9+
# 设置默认值
d.setdefault("gender", "男") # 键存在返回原值,不存在设置新值
六、相互转换
6.1 列表 ↔ 其他类型
lst = [1, 2, 3, 4, 5]
# 列表 → 字符串
s = str(lst) # "[1, 2, 3, 4, 5]"
s = ",".join(map(str, lst)) # "1,2,3,4,5"
# 列表 → 元组
t = tuple(lst) # (1, 2, 3, 4, 5)
# 列表 → 集合(去重)
s = set(lst) # {1, 2, 3, 4, 5}
# 列表 → 字典(需要键值对)
lst2 = [("a", 1), ("b", 2)]
d = dict(lst2) # {'a': 1, 'b': 2}
6.2 字符串 ↔ 其他类型
s = "hello"
# 字符串 → 列表
lst = list(s) # ['h', 'e', 'l', 'l', 'o']
lst = s.split() # ['hello']
# 字符串 → 元组
t = tuple(s) # ('h', 'e', 'l', 'l', 'o')
# 字符串 → 集合
s = set(s) # {'h', 'e', 'l', 'o'}
# 字符串 → 字典(需要解析)
import json
d = json.loads('{"name": "张三"}') # {'name': '张三'}
6.3 元组 ↔ 其他类型
t = (1, 2, 3, 4, 5)
# 元组 → 列表
lst = list(t) # [1, 2, 3, 4, 5]
# 元组 → 集合
s = set(t) # {1, 2, 3, 4, 5}
# 元组 → 字符串
s = str(t) # "(1, 2, 3, 4, 5)"
6.4 集合 ↔ 其他类型
s = {1, 2, 3, 4, 5}
# 集合 → 列表
lst = list(s) # [1, 2, 3, 4, 5](顺序不确定)
# 集合 → 元组
t = tuple(s) # (1, 2, 3, 4, 5)
# 集合 → 字符串
s_str = str(s) # "{1, 2, 3, 4, 5}"
6.5 字典 ↔ 其他类型
d = {"a": 1, "b": 2}
# 字典 → 列表
keys = list(d.keys()) # ['a', 'b']
values = list(d.values()) # [1, 2]
items = list(d.items()) # [('a', 1), ('b', 2)]
# 字典 → 字符串
s = str(d) # "{'a': 1, 'b': 2}"
s = json.dumps(d) # '{"a": 1, "b": 2}'(JSON格式)
# 字典 → 其他类型需要提取值或键
七、总结对比及选用指南
| 特性 | 列表 list | 字符串 str | 元组 tuple | 集合 set | 字典 dict |
|---|---|---|---|---|---|
| 有序性 | ✅ 有序 | ✅ 有序 | ✅ 有序 | ❌ 无序 | ✅ 有序(3.7+) |
| 可变性 | ✅ 可变 | ❌ 不可变 | ❌ 不可变 | ✅ 可变 | ✅ 可变 |
| 元素唯一 | ❌ 可重复 | ❌ 可重复 | ❌ 可重复 | ✅ 唯一 | ✅ 键唯一 |
| 索引支持 | ✅ | ✅ | ✅ | ❌ | ✅(键) |
| 切片支持 | ✅ | ✅ | ✅ | ❌ | ❌ |
| 适用场景 | 通用序列 | 文本处理 | 不可变序列 | 去重、集合运算 | 键值映射 |
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 存储有序数据且需要修改 | 列表 | 灵活,支持增删改 |
| 存储不可变的有序数据 | 元组 | 安全,性能好 |
| 文本处理 | 字符串 | 丰富的字符串方法 |
| 去重或集合运算 | 集合 | 自动去重,集合运算快 |
| 键值映射/查找 | 字典 | 通过键快速查找 |
三、Python传参
一、参数传递的底层原理
1.1 传递方式本质:对象引用传递(传对象引用)
Python 的参数传递既不是"值传递"也不是"引用传递",而是"对象引用传递"(Pass by Object Reference)。
| 概念 | 说明 |
|---|---|
| 不可变对象 | 函数内修改参数会创建新对象,不影响外部变量 |
| 可变对象 | 函数内修改参数会直接影响外部变量 |
# 不可变对象(int, str, tuple 等)
def modify_num(x):
x = x + 10
print("函数内:", x) # 20
a = 10
modify_num(a)
print("函数外:", a) # 10(不变)
# 可变对象(list, dict, set 等)
def modify_list(lst):
lst.append(4)
print("函数内:", lst) # [1, 2, 3, 4]
my_list = [1, 2, 3]
modify_list(my_list)
print("函数外:", my_list) # [1, 2, 3, 4](被修改)
二、Python 中的 5 种传参方式
2.1 位置参数(Positional Arguments)
定义:调用函数时按定义顺序传入参数,参数个数和顺序必须匹配。
def greet(name, age, city):
print(f"{name}, {age}岁, 来自{city}")
# 正确:按顺序传参
greet("张三", 25, "北京")
# 错误:顺序不对会导致逻辑错误
greet("北京", 25, "张三") # 语义错误
2.2 关键字参数(Keyword Arguments)
定义:调用时通过参数名指定传入的值,顺序可以任意。
def greet(name, age, city):
print(f"{name}, {age}岁, 来自{city}")
# 使用关键字参数
greet(name="张三", city="北京", age=25)
greet(city="上海", age=30, name="李四")
2.3 默认参数(Default Arguments)
定义:在函数定义时为参数提供默认值,调用时可以不传该参数。
def greet(name, age=18, city="北京"):
print(f"{name}, {age}岁, 来自{city}")
# 使用默认参数
greet("张三") # 张三, 18岁, 来自北京
greet("李四", 25) # 李四, 25岁, 来自北京
greet("王五", city="上海") # 王五, 18岁, 来自上海
⚠️ 默认参数的陷阱:默认参数在函数定义时只计算一次,如果默认值是可变对象(如列表),可能会产生意外行为。
# ❌ 错误示例:使用可变对象作为默认值
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2](意外!)
print(add_item(3)) # [1, 2, 3](意外!)
# ✅ 正确做法
def add_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [2](独立)
print(add_item(3)) # [3](独立)
2.4 可变位置参数(*args)
定义:收集所有多余的位置参数,打包成一个元组。
def sum_all(*args):
print("参数类型:", type(args)) # <class 'tuple'>
print("参数内容:", args)
return sum(args)
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
print(sum_all()) # 0(可以传0个)
2.5 可变关键字参数(**kwargs)
定义:收集所有多余的关键字参数,打包成一个字典。
def print_info(**kwargs):
print("参数类型:", type(kwargs)) # <class 'dict'>
print("参数内容:", kwargs)
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="张三", age=25, city="北京")
print_info() # 可以传0个
三、参数组合顺序
当多种参数类型同时使用时,必须遵循以下固定顺序:
1. 位置参数(必选参数) 2. *args(可变位置参数) 3. 默认参数(关键字参数) 4. **kwargs(可变关键字参数)
def demo(a, b, *args, c=10, d=20, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"c={c}, d={d}")
print(f"kwargs={kwargs}")
demo(1, 2, 3, 4, 5, c=100, e=50, f=60)
# 输出:
# a=1, b=2
# args=(3, 4, 5)
# c=100, d=20
# kwargs={'e': 50, 'f': 60}
四、参数解包(Unpacking)
4.1 解包列表/元组(*)
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6
# 元组解包
tup = (4, 5, 6)
print(add(*tup)) # 15
4.2 解包字典(**)
def greet(name, age, city):
print(f"{name}, {age}岁, 来自{city}")
person = {"name": "张三", "age": 25, "city": "北京"}
greet(**person) # 张三, 25岁, 来自北京
4.3 混合解包
def func(a, b, c, d=10, e=20):
print(f"a={a}, b={b}, c={c}, d={d}, e={e}")
args = [1, 2, 3]
kwargs = {"d": 100, "e": 200}
func(*args, **kwargs) # a=1, b=2, c=3, d=100, e=200
五、/ 和 * 分隔符
5.1 / 分隔符(Python 3.8+)
-
/之前的参数:只能按位置传递(positional-only) -
/之后的参数:可以按位置或关键字传递
def func(a, b, /, c, d):
print(a, b, c, d)
func(1, 2, 3, 4) # ✅ 正确
func(1, 2, c=3, d=4) # ✅ 正确
func(a=1, b=2, c=3, d=4) # ❌ 错误:a 和 b 不能使用关键字参数
5.2 * 分隔符
-
*之前的参数:可以按位置或关键字传递 -
*之后的参数:只能按关键字传递(keyword-only)
def func(a, b, *, c, d):
print(a, b, c, d)
func(1, 2, c=3, d=4) # ✅ 正确
func(1, 2, 3, 4) # ❌ 错误:c 和 d 必须使用关键字参数
5.3 同时使用 / 和 *
def func(a, b, /, c, *, d, e):
print(a, b, c, d, e)
func(1, 2, 3, d=4, e=5) # ✅ 正确
# func(1, 2, c=3, d=4, e=5) # ❌ 错误:a 和 b 不能使用关键字
# func(1, 2, 3, 4, 5) # ❌ 错误:d 和 e 必须使用关键字
六、参数传递方式对比表
| 传参方式 | 定义语法 | 调用语法 | 示例 | 特点 |
|---|---|---|---|---|
| 位置参数 | def f(a, b): |
f(1, 2) |
f(1, 2) |
按顺序传参 |
| 关键字参数 | def f(a, b): |
f(a=1, b=2) |
f(b=2, a=1) |
按名称传参,可调换顺序 |
| 默认参数 | def f(a, b=10): |
f(1) |
f(1) |
参数有默认值,可省略 |
| 可变位置参数 | def f(*args): |
f(1, 2, 3) |
f(1, 2, 3, 4, 5) |
接收任意数量位置参数 |
| 可变关键字参数 | def f(**kwargs): |
f(a=1, b=2) |
f(name="张三", age=25) |
接收任意数量关键字参数 |
| 位置只传 | def f(a, b, /): |
f(1, 2) |
f(1, 2) |
/ 前只能按位置传参 |
| 关键字只传 | def f(*, a, b): |
f(a=1, b=2) |
f(a=1, b=2) |
* 后只能按关键字传参 |
七、常见使用场景
场景1:不确定参数个数 → 使用 *args
def max_number(*args):
if not args:
return None
return max(args)
print(max_number(1, 5, 3, 9, 2)) # 9
场景2:需要接收任意关键字参数 → 使用 **kwargs
def save_user_info(**kwargs):
for key, value in kwargs.items():
print(f"保存 {key}: {value}")
save_user_info(name="张三", age=25, email="zhangsan@email.com")
场景3:装饰器 → 使用 *args, **kwargs
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"执行时间: {time.time() - start:.4f}秒")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
slow_function()
场景4:强制使用关键字参数(提高代码可读性)
def create_user(name, *, age, city):
print(f"创建用户: {name}, {age}岁, 来自{city}")
create_user("张三", age=25, city="北京") # ✅ 强制使用关键字
# create_user("张三", 25, "北京") # ❌ 错误
八、args 和 kwargs 命名惯例
| 命名 | 含义 | 说明 |
|---|---|---|
*args |
arguments | 位置参数元组(可自定义,如 *params) |
**kwargs |
keyword arguments | 关键字参数字典(可自定义,如 **options) |
# 自定义名称(不推荐)
def func(*params, **options):
pass
# 标准命名(推荐)
def func(*args, **kwargs):
pass
九、参数传递优先级总结
调用函数时,Python 按照以下顺序解析参数:
def demo(a, b, *args, c=10, d=20, **kwargs):
pass
demo(1, 2, 3, 4, 5, c=100, e=50, f=60)
-
位置参数:
a=1, b=2 -
*args:收集多余的位置参数(3, 4, 5) -
默认参数:
c=100(覆盖默认值10),d=20 -
**kwargs:收集多余的关键字参数{'e': 50, 'f': 60}
四、Python高级
一、类型注解
1.1 基本概念
类型注解(Type Hints)是Python 3.5+引入的功能,用于声明变量、函数参数和返回值的预期类型。
# 没有类型注解
def greet(name):
return f"Hello, {name}"
# 有类型注解
def greet(name: str) -> str:
return f"Hello, {name}"
2.1 基础数据类型注解
# 整数 age: int = 25 # 浮点数 price: float = 99.99 # 字符串 name: str = "张三" # 布尔值 is_active: bool = True # 字节 data: bytes = b"hello" # None result: None = None
注解的多种写法
# 方式1:变量名: 类型 = 值 name: str = "Alice" # 方式2:变量名: 类型(不赋值) age: int # 方式3:直接赋值(类型推断) city = "北京" # IDE会自动推断为str类型
2.3 容器类型注解
列表(List)
from typing import List # Python 3.9+ 可以直接使用 list # 旧版本需要 from typing import List # 整数列表 numbers: list[int] = [1, 2, 3, 4, 5] # 字符串列表 names: list[str] = ["张三", "李四", "王五"] # 混合类型列表 mixed: list[int | str] = [1, "hello", 2, "world"] # 嵌套列表 matrix: list[list[int]] = [[1, 2], [3, 4]] # 任意类型列表 any_list: list = [1, "a", True] # 不推荐
元组(Tuple)
from typing import Tuple
# 固定长度元组
user: tuple[str, int] = ("张三", 25) # 2个元素
point: tuple[int, int] = (10, 20) # 2个整数
person: tuple[str, int, float] = ("李四", 30, 1.75)
# 可变长度元组
scores: tuple[int, ...] = (90, 85, 88, 92) # 任意数量整数
# 空元组
empty: tuple = ()
# 单元素元组(注意逗号)
single: tuple[int] = (5,) # 类型是tuple[int],而不是int
字典(Dict)
from typing import Dict
# Python 3.9+
# 字符串键,整数值
scores: dict[str, int] = {"数学": 95, "英语": 88, "语文": 92}
# 字符串键,字符串值
config: dict[str, str] = {"host": "localhost", "port": "8080"}
# 整数键,列表值
data: dict[int, list[str]] = {
1: ["苹果", "香蕉"],
2: ["橙子", "葡萄"]
}
# 复杂的嵌套字典
user_data: dict[str, dict[str, int | str]] = {
"张三": {"age": 25, "score": 95},
"李四": {"age": 30, "score": 88}
}
集合(Set)
2.4 参数注解及返回值注解
# 参数注解和返回值注解
def calculate_area(length: float, width: float) -> float:
"""计算矩形面积"""
return length * width
# 没有返回值
def log_message(msg: str) -> None:
print(f"[LOG] {msg}")
# 多参数
def create_user(name: str, age: int, email: str = "") -> dict[str, str | int]:
return {"name": name, "age": age, "email": email}
二、模块
一、模块的定义及使用
模块中import和from区别与联系
一句话说清楚核心区别:import 是“连人带家伙全请进来”,from...import 是“只请某个人进来,不用带他的家当”。
假设你有个工具包(模块)叫 小明,里面有一把锤子 hanmer 和一个扳手 wrench。
import 小明:你把小明整个工具箱搬进你家。
用的时候得说:小明.锤子、小明.扳手。
好处:你知道这工具是小明的,不会和自家的东西搞混。
from 小明 import 锤子:你只把锤子拿出来放自己兜里。
用的时候直接说:锤子。
好处:打字快,代码简洁。
坏处:如果自家也有个叫“锤子”的东西,就会覆盖掉,容易出问题。
代码层面区别
math_utils.py:
# math_utils.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
import方式:import math_utils
import math_utils # 必须用模块名.函数名 的方式调用 result1 = math_utils.add(1, 2) # ✅ 正确 result2 = math_utils.multiply(3, 4) # ✅ 正确 # 下面这种写法会报错(找不到 add) # result = add(1, 2) # ❌ NameError: name 'add' is not defined
from方式:from math_utils import add
from math_utils import add # 可以直接用函数名调用,不用加前缀 result = add(1, 2) # ✅ 正确 # 但 multiply 没被导入,用不了 # result = multiply(3, 4) # ❌ NameError
通配符导入:from math_utils import *
from math_utils import * # 模块里所有的东西都直接拿出来 result1 = add(1, 2) # ✅ result2 = multiply(3, 4) # ✅
使用场景对比
-
import 模块:把整个模块请进来,调用时加前缀模块.,安全、清晰。 -
from 模块 import 东西:只把部分功能拿进来,直接调用,简洁、方便,但注意命名冲突。
新手建议:在不确定是否会冲突时,先用 import 模块,更安全,也更容易看懂代码。
| 场景 | 推荐写法 | 原因 |
|---|---|---|
| 只用模块里的1-2个函数 | from 模块 import 函数名 |
代码简洁,少打几个字 |
| 要用模块里的很多功能 | import 模块 |
防止函数名冲突,一看就知道来自哪个模块 |
| 两个库有同名函数 | 必须用 import 模块 |
例如 os.path 和 Path,不区分会覆盖 |
| 写大型项目/团队协作 | 推荐 import 模块 |
代码可读性强,明确来源 |
| 交互式命令行(随手测试) | 可以用 from...import |
方便快捷 |
__all__关键字
__all__ 是 Python 中一个特殊的模块级变量,用于控制 from module import * 时哪些内容会被导入。它本质上是一个白名单,显式声明模块对外公开的接口。
示例:mymodule.py
# mymodule.py
# 对外公开的接口
__all__ = ["public_func", "PublicClass"]
def public_func():
print("这是公开函数")
def _private_func():
print("这是私有函数(以下划线开头)")
class PublicClass:
pass
class _PrivateClass:
pass
# 未在 __all__ 中列出的函数
def hidden_func():
print("这个函数不会在 import * 中被导入")
使用
# 在另一个文件中 from mymodule import * public_func() # ✅ 可以调用 obj = PublicClass() # ✅ 可以实例化 # hidden_func() # ❌ NameError: 未定义(不在 __all__ 中) # _private_func() # ❌ NameError: 未定义
| 导入方式 | __all__ 是否生效 | 导入内容 |
|---|---|---|
from module import * |
✅ 生效 | 只导入 __all__ 中列出的名称 |
from module import name |
❌ 不生效 | 只导入指定的 name |
import module |
❌ 不生效 | 导入整个模块,通过 module.xxx 访问 |
# __all__ 只影响 from ... import * 这一种导入方式! import mymodule mymodule.hidden_func() # ✅ 可以访问(模块本身被完整加载)
二、Python 常用内置模块及功能
| 模块 | 主要用途 | 常用函数/类 |
|---|---|---|
json |
JSON 数据处理 | dumps, loads, dump, load |
pickle |
Python 对象序列化 | dumps, loads, dump, load |
csv |
CSV 文件读写 | reader, writer, DictReader |
os |
操作系统接口 | listdir, mkdir, path.join |
sys |
解释器相关 | argv, exit, path |
shutil |
高级文件操作 | copy, copytree, rmtree |
glob |
文件通配符 | glob |
datetime |
日期时间 | now, strftime, timedelta |
time |
时间操作 | time, sleep, perf_counter |
math |
数学函数 | sqrt, ceil, floor, pi |
random |
随机数生成 | randint, choice, shuffle |
statistics |
统计函数 | mean, median, stdev |
re |
正则表达式 | match, search, findall |
collections |
高级容器 | defaultdict, Counter, deque |
itertools |
迭代器工具 | chain, product, combinations |
urllib |
URL 处理 | urlopen, urlencode |
logging |
日志记录 | info, error, basicConfig |
hashlib |
哈希算法 | md5, sha256 |
copy |
对象拷贝 | copy, deepcopy |
typing |
类型注解 | List, Dict, Optional |
json——JSON 数据编解码
| 函数 | 说明 | 示例 |
|---|---|---|
json.dumps(obj) |
将 Python 对象转为 JSON 字符串 | json.dumps({"a": 1}) → '{"a": 1}' |
json.loads(json_str) |
将 JSON 字符串转为 Python 对象 | json.loads('{"a": 1}') → {'a': 1} |
json.dump(obj, file) |
将 Python 对象写入文件(JSON 格式) | json.dump(data, f) |
json.load(file) |
从 JSON 文件读取数据 | data = json.load(f) |
import json
# 编码
data = {"name": "张三", "age": 25, "hobbies": ["读书", "跑步"]}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
# 解码
restored = json.loads(json_str)
print(restored["name"]) # 张三
# 读写文件
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
pickle-----Python对象序列化
| 函数 | 说明 | 示例 |
|---|---|---|
pickle.dumps(obj) |
将 Python 对象序列化为字节串 | pickle.dumps([1,2,3]) |
pickle.loads(bytes) |
从字节串反序列化 Python 对象 | pickle.loads(data) |
pickle.dump(obj, file) |
将 Python 对象写入文件 | pickle.dump(obj, f) |
pickle.load(file) |
从文件读取 Python 对象 | obj = pickle.load(f) |
import pickle
data = {"name": "张三", "scores": [85, 92, 78]}
# 序列化到文件
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
# 从文件读取
with open("data.pkl", "rb") as f:
loaded = pickle.load(f)
print(loaded) # {'name': '张三', 'scores': [85, 92, 78]}
csv----CSV文件读写
| 函数/类 | 说明 | 示例 |
|---|---|---|
csv.reader(file) |
创建 CSV 读取器 | reader = csv.reader(f) |
csv.writer(file) |
创建 CSV 写入器 | writer = csv.writer(f) |
csv.DictReader(file) |
读取为字典(首行为表头) | reader = csv.DictReader(f) |
csv.DictWriter(file, fieldnames) |
写入字典数据 | writer = csv.DictWriter(f, fieldnames) |
import csv
# 写入 CSV
with open("students.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["姓名", "年龄", "城市"])
writer.writerow(["张三", 25, "北京"])
writer.writerow(["李四", 30, "上海"])
# 读取 CSV
with open("students.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
print(row)
# DictReader 方式(首行为表头)
with open("students.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["姓名"], row["年龄"])
os----操作系统接口
| 函数 | 说明 | 示例 |
|---|---|---|
os.getcwd() |
获取当前工作目录 | os.getcwd() → '/home/user' |
os.chdir(path) |
切换工作目录 | os.chdir("/tmp") |
os.listdir(path) |
列出目录内容 | os.listdir(".") → ['file1.py', 'dir1'] |
os.mkdir(path) |
创建单级目录 | os.mkdir("new_folder") |
os.makedirs(path) |
创建多级目录 | os.makedirs("a/b/c") |
os.remove(path) |
删除文件 | os.remove("file.txt") |
os.rmdir(path) |
删除空目录 | os.rmdir("empty_dir") |
os.removedirs(path) |
删除多级空目录 | os.removedirs("a/b/c") |
os.rename(old, new) |
重命名文件/目录 | os.rename("old.txt", "new.txt") |
os.path.exists(path) |
判断路径是否存在 | os.path.exists("file.txt") → True |
os.path.isfile(path) |
判断是否是文件 | os.path.isfile("file.txt") → True |
os.path.isdir(path) |
判断是否是目录 | os.path.isdir("folder") → True |
os.path.join(a, b) |
拼接路径 | os.path.join("dir", "file.txt") → 'dir/file.txt' |
os.path.basename(path) |
获取文件名 | os.path.basename("/a/b/c.txt") → 'c.txt' |
os.path.dirname(path) |
获取目录名 | os.path.dirname("/a/b/c.txt") → '/a/b' |
os.path.splitext(path) |
分离文件名和扩展名 | os.path.splitext("file.txt") → ('file', '.txt') |
os.environ |
获取环境变量 | os.environ.get("PATH") |
import os
# 当前目录
print(os.getcwd())
# 创建目录
os.makedirs("data/2024/01", exist_ok=True)
# 遍历目录
for filename in os.listdir("."):
if filename.endswith(".py"):
print(f"Python 文件: {filename}")
# 路径操作
path = os.path.join("data", "2024", "01", "report.txt")
print(os.path.basename(path)) # report.txt
print(os.path.dirname(path)) # data/2024/01
print(os.path.splitext(path)) # ('data/2024/01/report', '.txt')
sys----Python解释器相关
| 函数/属性 | 说明 | 示例 |
|---|---|---|
sys.argv |
命令行参数列表 | sys.argv[0] 是脚本名 |
sys.exit(code) |
退出程序 | sys.exit(0) |
sys.path |
模块搜索路径列表 | sys.path.append("/my/modules") |
sys.version |
Python 版本信息 | sys.version → '3.12.0' |
sys.platform |
操作系统平台 | sys.platform → 'win32' / 'linux' |
sys.stdin |
标准输入 | sys.stdin.read() |
sys.stdout |
标准输出 | sys.stdout.write("Hello") |
sys.stderr |
标准错误 | sys.stderr.write("Error!") |
sys.getsizeof(obj) |
获取对象内存大小(字节) | sys.getsizeof([1,2,3]) |
import sys
# 命令行参数
# python script.py arg1 arg2
print(f"脚本名: {sys.argv[0]}")
print(f"参数: {sys.argv[1:]}")
# 添加模块搜索路径
sys.path.append("/custom/modules")
# 获取 Python 版本
print(f"Python 版本: {sys.version}")
# 退出程序
if len(sys.argv) < 2:
print("请提供参数!")
sys.exit(1)
shutil----高级文件操作
| 函数 | 说明 | 示例 |
|---|---|---|
shutil.copy(src, dst) |
复制文件 | shutil.copy("a.txt", "b.txt") |
shutil.copytree(src, dst) |
递归复制目录 | shutil.copytree("src_dir", "dst_dir") |
shutil.move(src, dst) |
移动文件/目录 | shutil.move("a.txt", "new_dir/") |
shutil.rmtree(path) |
递归删除目录 | shutil.rmtree("folder") |
shutil.make_archive(base, format, root) |
创建压缩包 | shutil.make_archive("backup", "zip", "data/") |
shutil.disk_usage(path) |
获取磁盘使用情况 | shutil.disk_usage("/") |
import shutil
# 复制文件
shutil.copy("source.txt", "backup.txt")
# 删除目录(包括所有内容)
shutil.rmtree("temp_folder", ignore_errors=True)
# 创建 zip 压缩包
shutil.make_archive("backup", "zip", "data")
# 获取磁盘空间
total, used, free = shutil.disk_usage("/")
print(f"可用空间: {free // 1024**3} GB")
glob----文件通配符匹配
| 函数 | 说明 | 示例 |
|---|---|---|
glob.glob(pattern) |
返回匹配的文件列表 | glob.glob("*.py") |
glob.iglob(pattern) |
返回迭代器(节省内存) | for f in glob.iglob("*.txt"): |
import glob
# 查找所有 Python 文件
py_files = glob.glob("*.py")
print(py_files)
# 递归查找
all_files = glob.glob("**/*.txt", recursive=True)
# 查找特定模式
log_files = glob.glob("logs/*.log")
datetime——日期时间处理
| 类/函数 | 说明 | 示例 |
|---|---|---|
datetime.now() |
获取当前时间 | datetime.now() |
datetime(year, month, day) |
创建日期对象 | datetime(2024, 1, 15) |
date.today() |
获取当前日期 | date.today() |
date(year, month, day) |
创建日期对象 | date(2024, 1, 15) |
timedelta(days, hours, ...) |
时间差 | timedelta(days=7) |
strftime(format) |
格式化日期为字符串 | now.strftime("%Y-%m-%d") |
strptime(date_str, format) |
将字符串解析为日期 | datetime.strptime("2024-01-15", "%Y-%m-%d") |
from datetime import datetime, date, timedelta
# 当前时间
now = datetime.now()
print(now) # 2024-01-15 14:30:25.123456
print(now.strftime("%Y年%m月%d日 %H:%M:%S")) # 2024年01月15日 14:30:25
# 日期运算
today = date.today()
tomorrow = today + timedelta(days=1)
last_week = today - timedelta(days=7)
print(f"明天: {tomorrow}")
# 字符串解析
date_str = "2024-12-25 10:30:00"
parsed = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(parsed)
# 格式化格式速查
# %Y: 2024 %m: 01 %d: 15 %H: 14 %M: 30 %S: 25
# %A: 星期一 %B: 一月
time——时间相关操作
| 函数 | 说明 | 示例 |
|---|---|---|
time.time() |
获取时间戳(秒) | time.time() → 1705317000.123 |
time.sleep(seconds) |
程序暂停指定秒数 | time.sleep(1) |
time.localtime() |
时间戳转本地时间元组 | time.localtime() |
time.strftime(format) |
格式化时间 | time.strftime("%Y-%m-%d") |
time.perf_counter() |
高精度计时(性能测试) | start = time.perf_counter() |
import time
# 计时器
start = time.perf_counter()
# 执行一些操作
time.sleep(0.5)
elapsed = time.perf_counter() - start
print(f"耗时: {elapsed:.4f} 秒")
# 时间戳
timestamp = time.time()
print(f"时间戳: {timestamp}")
# 暂停
print("开始...")
time.sleep(2)
print("继续...")
math——数学函数
| 函数/常量 | 说明 | 示例 |
|---|---|---|
math.pi |
圆周率 π | math.pi → 3.141592... |
math.e |
自然常数 e | math.e → 2.718281... |
math.sqrt(x) |
平方根 | math.sqrt(16) → 4.0 |
math.pow(x, y) |
幂运算 | math.pow(2, 3) → 8.0 |
math.ceil(x) |
向上取整 | math.ceil(3.2) → 4 |
math.floor(x) |
向下取整 | math.floor(3.8) → 3 |
math.round(x) |
四舍五入 | round(3.5) → 4 |
math.fabs(x) |
绝对值 | math.fabs(-5) → 5.0 |
math.sin(x) / math.cos(x) |
三角函数(弧度) | math.sin(math.pi/2) → 1.0 |
math.radians(deg) |
角度转弧度 | math.radians(180) → 3.14159 |
math.degrees(rad) |
弧度转角度 | math.degrees(math.pi) → 180.0 |
math.log(x, base) |
对数 | math.log(100, 10) → 2.0 |
math.comb(n, k) |
组合数 C(n,k) | math.comb(5, 2) → 10 |
math.perm(n, k) |
排列数 P(n,k) | math.perm(5, 2) → 20 |
math.factorial(n) |
阶乘 | math.factorial(5) → 120 |
import math print(math.pi) # 3.141592653589793 print(math.sqrt(64)) # 8.0 print(math.ceil(3.2)) # 4 print(math.floor(3.8)) # 3 print(math.comb(5, 2)) # 10(从5个中选2个) print(math.factorial(5)) # 120
random——随机数生成
| 函数 | 说明 | 示例 |
|---|---|---|
random.random() |
生成 [0, 1) 间的浮点数 | random.random() → 0.374 |
random.randint(a, b) |
生成 [a, b] 间的整数 | random.randint(1, 10) |
random.randrange(start, stop, step) |
生成指定步长的整数 | random.randrange(0, 10, 2) |
random.choice(seq) |
从序列中随机选一个元素 | random.choice(["a","b","c"]) |
random.choices(seq, k=n) |
从序列中随机选 n 个元素(可重复) | random.choices(["a","b"], k=3) |
random.sample(seq, k) |
从序列中随机选 k 个元素(不重复) | random.sample(range(10), 3) |
random.shuffle(lst) |
打乱列表顺序 | random.shuffle(cards) |
random.seed(n) |
设置随机种子(可复现) | random.seed(42) |
random.uniform(a, b) |
生成 [a, b] 间的浮点数 | random.uniform(1.0, 5.0) |
import random # 设置随机种子(结果可复现) random.seed(42) print(random.random()) # 0.6394267984578837 print(random.randint(1, 100)) # 82 print(random.choice(["苹果", "香蕉", "橙子"])) # 橙子 # 洗牌 cards = ["A", "2", "3", "4", "5"] random.shuffle(cards) print(cards) # ['3', 'A', '5', '4', '2'] # 随机抽样(不重复) lottery = random.sample(range(1, 50), 6) print(lottery) # [12, 3, 45, 22, 9, 38]
statistics——统计函数
| 函数 | 说明 | 示例 |
|---|---|---|
statistics.mean(data) |
算术平均数 | mean([1,2,3,4,5]) → 3.0 |
statistics.median(data) |
中位数 | median([1,2,3,4,5]) → 3 |
statistics.mode(data) |
众数(出现最多的值) | mode([1,1,2,2,2,3]) → 2 |
statistics.stdev(data) |
样本标准差 | stdev([1,2,3,4,5]) → 1.58 |
statistics.variance(data) |
样本方差 | variance([1,2,3,4,5]) → 2.5 |
statistics.quantiles(data, n) |
分位数 | quantiles([1,2,3,4,5], n=4) |
import statistics
scores = [85, 92, 78, 90, 88, 92, 76]
print(f"平均分: {statistics.mean(scores):.2f}") # 85.86
print(f"中位数: {statistics.median(scores)}") # 88
print(f"众数: {statistics.mode(scores)}") # 92
print(f"标准差: {statistics.stdev(scores):.2f}") # 6.23
re——正则表达式
| 函数 | 说明 | 示例 |
|---|---|---|
re.match(pattern, str) |
从开头匹配 | re.match(r"\d+", "123abc") |
re.search(pattern, str) |
搜索第一个匹配 | re.search(r"\d+", "abc123def") |
re.findall(pattern, str) |
查找所有匹配 | re.findall(r"\d+", "a1b2c3") → ['1','2','3'] |
re.finditer(pattern, str) |
查找所有匹配(迭代器) | re.finditer(r"\d+", text) |
re.sub(pattern, repl, str) |
替换匹配内容 | re.sub(r"\d+", "X", "a1b2") → 'aXbX' |
re.split(pattern, str) |
按正则分割 | re.split(r"[,\s]+", "a,b c") → ['a','b','c'] |
re.compile(pattern) |
编译正则(提高性能) | pattern = re.compile(r"\d+") |
import re
text = "我的电话是 138-1234-5678,邮箱是 abc@example.com"
# 查找所有数字
numbers = re.findall(r"\d+", text)
print(numbers) # ['138', '1234', '5678']
# 搜索邮箱
email = re.search(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
if email:
print(email.group()) # abc@example.com
# 替换
masked = re.sub(r"\d", "X", text)
print(masked)
# 编译正则(性能更好,尤其循环中)
pattern = re.compile(r"\d{3}-\d{4}-\d{4}")
phone = pattern.search("138-1234-5678")
print(phone.group()) # 138-1234-5678
collections——高级容器类型
| 类型 | 说明 | 示例 |
|---|---|---|
defaultdict(factory) |
带默认值的字典 | d = defaultdict(int) |
Counter(iterable) |
计数器(统计频率) | Counter("hello") → {'l':2, 'h':1, ...} |
OrderedDict() |
有序字典(Python 3.7+ 内置 dict 已有序) | OrderedDict([('a',1), ('b',2)]) |
deque(iterable) |
双端队列(高效两端操作) | dq = deque([1,2,3]) |
namedtuple(name, fields) |
具名元组 | Point = namedtuple('Point', ['x', 'y']) |
from collections import defaultdict, Counter, deque, namedtuple
# defaultdict
d = defaultdict(int)
d["a"] += 1
d["b"] += 2
print(d) # {'a': 1, 'b': 2}
# Counter
words = "hello world hello python"
counter = Counter(words.split())
print(counter) # {'hello': 2, 'world': 1, 'python': 1}
print(counter.most_common(1)) # [('hello', 2)]
# deque(两端操作高效)
dq = deque([1, 2, 3])
dq.appendleft(0)
dq.append(4)
print(dq) # deque([0, 1, 2, 3, 4])
dq.popleft()
dq.pop()
# namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y) # 10 20
print(p[0], p[1]) # 10 20(支持索引)
itertools——迭代器工具
| 函数 | 说明 | 示例 |
|---|---|---|
itertools.count(start, step) |
无限计数器 | for i in count(1, 2): |
itertools.cycle(iterable) |
无限循环迭代 | for x in cycle([1,2,3]): |
itertools.repeat(value, n) |
重复生成值 | list(repeat(5, 3)) → [5,5,5] |
itertools.chain(*iterables) |
拼接多个迭代器 | chain([1,2], [3,4]) |
itertools.product(*iterables) |
笛卡尔积 | product([1,2], ['a','b']) |
itertools.permutations(iterable, r) |
排列 | permutations([1,2,3], 2) |
itertools.combinations(iterable, r) |
组合 | combinations([1,2,3], 2) |
itertools.groupby(iterable, key) |
按 key 分组 | groupby(data, key=lambda x: x[0]) |
from itertools import chain, product, combinations, permutations
# 拼接
print(list(chain([1, 2], [3, 4], [5, 6]))) # [1, 2, 3, 4, 5, 6]
# 笛卡尔积
colors = ["红", "蓝"]
sizes = ["S", "M", "L"]
for item in product(colors, sizes):
print(item) # ('红','S'), ('红','M'), ...
# 组合(从 3 个中选 2 个)
print(list(combinations([1, 2, 3], 2))) # [(1,2), (1,3), (2,3)]
# 排列(从 3 个中选 2 个,有序)
print(list(permutations([1, 2, 3], 2))) # [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]
urllib——URL 处理(HTTP 请求)
💡 建议:实际项目中推荐使用 requests 模块(第三方,更易用)。
| 函数/类 | 说明 | 示例 |
|---|---|---|
urllib.request.urlopen(url) |
发送 HTTP 请求 | response = urlopen("https://api.example.com") |
urllib.parse.urlencode(params) |
编码 URL 参数 | urlencode({"q": "python"}) |
import urllib.request
import urllib.parse
# 发送 GET 请求
response = urllib.request.urlopen("https://httpbin.org/get")
data = response.read().decode("utf-8")
print(data)
# POST 请求
params = urllib.parse.urlencode({"name": "张三", "age": 25})
req = urllib.request.Request(
"https://httpbin.org/post",
data=params.encode("utf-8"),
method="POST"
)
response = urllib.request.urlopen(req)
print(response.read().decode("utf-8"))
logging——日志记录
| 函数 | 说明 | 示例 |
|---|---|---|
logging.debug(msg) |
调试信息 | logging.debug("变量值: 10") |
logging.info(msg) |
一般信息 | logging.info("程序启动") |
logging.warning(msg) |
警告信息 | logging.warning("内存不足") |
logging.error(msg) |
错误信息 | logging.error("文件未找到") |
logging.critical(msg) |
严重错误 | logging.critical("系统崩溃") |
logging.basicConfig() |
配置日志格式 | logging.basicConfig(level=logging.INFO) |
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
filename="app.log",
filemode="a"
)
# 使用日志
logging.info("程序启动")
try:
result = 10 / 0
except ZeroDivisionError as e:
logging.error(f"发生错误: {e}")
hashlib——哈希算法
| 函数/类 | 说明 | 示例 |
|---|---|---|
hashlib.md5() |
MD5 哈希 | hashlib.md5(b"hello").hexdigest() |
hashlib.sha1() |
SHA1 哈希 | hashlib.sha1(b"hello").hexdigest() |
hashlib.sha256() |
SHA256 哈希 | hashlib.sha256(b"hello").hexdigest() |
hashlib.sha512() |
SHA512 哈希 | hashlib.sha512(b"hello").hexdigest() |
import hashlib
# 计算文件 MD5
def get_file_md5(filename):
md5 = hashlib.md5()
with open(filename, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
md5.update(chunk)
return md5.hexdigest()
# 密码哈希
password = "my_password"
hashed = hashlib.sha256(password.encode()).hexdigest()
print(hashed)
copy——对象拷贝
| 函数 | 说明 | 示例 |
|---|---|---|
copy.copy(obj) |
浅拷贝 | copy.copy(list1) |
copy.deepcopy(obj) |
深拷贝 | copy.deepcopy(list1) |
import copy lst1 = [[1, 2], [3, 4]] lst2 = copy.copy(lst1) # 浅拷贝 lst3 = copy.deepcopy(lst1) # 深拷贝 lst1[0][0] = 999 print(lst2) # [[999, 2], [3, 4]](浅拷贝受影响) print(lst3) # [[1, 2], [3, 4]](深拷贝不受影响)
typing——类型注解
from typing import List, Dict, Optional, Tuple, Union, Any
def process_data(data: List[int]) -> Dict[str, int]:
return {"sum": sum(data)}
def get_user(name: str, age: Optional[int] = None) -> Dict[str, Union[str, int]]:
user = {"name": name}
if age is not None:
user["age"] = age
return user
五、Python面向对象
一、类与对象基础
1.1 类的定义与实例化
class Student:
"""学生类"""
# 类属性(所有实例共享)
school = "北京大学"
# 构造方法:初始化实例
def __init__(self, name, age, score):
# 实例属性
self.name = name
self.age = age
self.score = score
# 实例方法
def study(self, hours):
print(f"{self.name} 学习了 {hours} 小时")
# 创建实例
s1 = Student("张三", 20, 85)
s2 = Student("李四", 22, 92)
# 访问属性
print(s1.name) # 张三
print(s1.school) # 北京大学(类属性)
# 调用方法
s1.study(3) # 张三 学习了 3 小时
self关键字
| 概念 | 说明 |
|---|---|
self |
代表实例本身,是实例方法的第一个参数 |
| 作用 | 在类内部访问实例的属性和方法 |
| 命名 | 约定俗成叫 self,可以改名但不建议 |
class Person: def __init__(self, name): self.name = name # self 绑定实例属性 def introduce(self): print(f"我是 {self.name}") # 通过 self 访问实例属性 # 调用时 Python 自动传入 self p = Person("张三") p.introduce() # 等价于 Person.introduce(p)
1.2 类属性与实例属性的区别
| 属性类型 | 定义位置 | 访问方式 | 存储位置 |
|---|---|---|---|
| 类属性 | 类内部,方法外部 | 类名.属性 或 实例.属性 |
类本身 |
| 实例属性 | __init__ 中用 self.属性 |
实例.属性 |
每个实例独立 |
class Car:
# 类属性(所有实例共享)
wheels = 4
def __init__(self, brand, color):
# 实例属性(每个实例独立)
self.brand = brand
self.color = color
c1 = Car("特斯拉", "红色")
c2 = Car("宝马", "蓝色")
print(c1.wheels) # 4(类属性)
print(Car.wheels) # 4(类属性)
c1.wheels = 5 # 创建实例属性,不影响类属性
print(c1.wheels) # 5
print(Car.wheels) # 4
1.3 实例方法、类方法、静态方法区别
| 方法类型 | 第一个参数 | 装饰器 | 访问权限 | 适用场景 |
|---|---|---|---|---|
| 实例方法 | self(实例) |
无 | 可访问实例和类属性 | 需要操作实例数据 |
| 类方法 | cls(类) |
@classmethod |
只能访问类属性 | 操作类级别数据 |
| 静态方法 | 无(不自动传入) | @staticmethod |
不能访问实例/类属性 | 工具函数,与类相关 |
class Example:
class_attr = "类属性"
def __init__(self, value):
self.value = value
# 实例方法
def instance_method(self):
return f"实例方法: {self.value}, {self.class_attr}"
# 类方法
@classmethod
def class_method(cls):
return f"类方法: {cls.class_attr}"
# 静态方法
@staticmethod
def static_method():
return "静态方法: 无法访问实例或类属性"
e = Example("hello")
print(e.instance_method()) # 实例方法: hello, 类属性
print(Example.class_method()) # 类方法: 类属性
print(Example.static_method()) # 静态方法: 无法访问实例或类属性
实例方法(Instance Method)
class Student:
school = "北京大学"
def __init__(self, name, score):
self.name = name
self.score = score
# 实例方法
def get_score(self):
return self.score
def update_score(self, new_score):
self.score = new_score
def introduce(self):
print(f"我叫 {self.name},来自 {self.school}")
s = Student("张三", 85)
print(s.get_score()) # 85
s.update_score(90)
print(s.get_score()) # 90
s.introduce() # 我叫 张三,来自 北京大学
类方法
第一个参数是 cls,表示类本身。使用 @classmethod 装饰器。
-
工厂方法(创建实例)
-
操作类属性
-
替代构造函数
class Student:
school = "北京大学"
count = 0
def __init__(self, name):
self.name = name
Student.count += 1
# 类方法
@classmethod
def get_school(cls):
return cls.school
@classmethod
def set_school(cls, new_school):
cls.school = new_school
@classmethod
def get_count(cls):
return cls.count
# 通过类调用
print(Student.get_school()) # 北京大学
Student.set_school("清华大学")
print(Student.get_school()) # 清华大学
# 通过实例调用(也能工作,但建议用类)
s = Student("张三")
print(s.get_school()) # 清华大学
静态方法(Static Method)
使用 @staticmethod 装饰器,不自动传入 self 或 cls。
-
工具函数
-
与类逻辑相关但不需要访问实例/类数据的函数
class MathUtils:
# 静态方法:与类相关但不需要实例或类数据
@staticmethod
def add(a, b):
return a + b
@staticmethod
def is_even(n):
return n % 2 == 0
@staticmethod
def factorial(n):
if n <= 1:
return 1
return n * MathUtils.factorial(n - 1)
# 通过类调用
print(MathUtils.add(3, 5)) # 8
print(MathUtils.is_even(10)) # True
print(MathUtils.factorial(5)) # 120
# 通过实例调用(也能工作)
math = MathUtils()
print(math.add(2, 3)) # 5
1.4 魔法方法
官方文档:https://docs.python.org/zh-cn/3/reference/datamodel.html#special-method-names
魔法方法是以双下划线开头和结尾的特殊方法(如 __init__),在特定操作时自动调用。(相当于在Java中方法的重写)
| 特征 | 说明 |
|---|---|
| 命名格式 | __method__(双下划线) |
| 调用方式 | 自动调用,通常不直接调用 |
| 作用 | 实现对象的各种行为(初始化、运算、比较等) |
对象的初始化与销毁
| 方法 | 触发时机 | 示例 |
|---|---|---|
__init__(self, ...) |
实例化时 | obj = MyClass() |
__new__(cls, ...) |
创建实例时(先于 __init__) |
单例模式 |
__del__(self) |
实例被销毁时 | del obj |
class Person:
def __new__(cls, name):
print(f"1. __new__ 被调用,创建 {name}")
return super().__new__(cls)
def __init__(self, name):
print(f"2. __init__ 被调用,初始化 {name}")
self.name = name
def __del__(self):
print(f"3. __del__ 被调用,{self.name} 被销毁")
p = Person("张三")
del p
# 输出:
# 1. __new__ 被调用,创建 张三
# 2. __init__ 被调用,初始化 张三
# 3. __del__ 被调用,张三 被销毁
比较运算符
| 方法 | 运算符 | 用途 |
|---|---|---|
__eq__(self, other) |
== |
等于 |
__ne__(self, other) |
!= |
不等于 |
__lt__(self, other) |
< |
小于 |
__le__(self, other) |
<= |
小于等于 |
__gt__(self, other) |
> |
大于 |
__ge__(self, other) |
>= |
大于等于 |
class Score:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value < other.value
def __gt__(self, other):
return self.value > other.value
def __repr__(self):
return f"Score({self.value})"
s1 = Score(85)
s2 = Score(90)
s3 = Score(85)
print(s1 == s2) # False
print(s1 == s3) # True
print(s1 < s2) # True
print(s2 > s1) # True

浙公网安备 33010602011771号