
本期分享:
5. 列表复制不能只用赋值
6. 函数默认参数不要使用可变对象
7. 遍历列表时不要直接删除元素
8. 字典取值推荐使用 get 和 setdefault
Python 的 list 和 dict 非常好用,也是 AI 项目里处理数据、配置、请求参数时最常见的数据结构。但它们都是可变对象,很多“明明只改了一个地方,为什么其他地方也变了”的问题都和它有关。
5. 列表复制不能只用赋值
赋值不会复制列表,只是多了一个名字指向同一个对象。
old_users = ["Tom", "Jerry"]new_users = old_usersnew_users.append("Alice")print(old_users) # ['Tom', 'Jerry', 'Alice']
如果只是复制一层列表,可以使用:
new_users = old_users.copy()
或者:
new_users = old_users[:]
如果列表里还有嵌套列表或字典,需要考虑深拷贝:
from copy import deepcopyusers = [{"name": "Tom", "tags": ["admin"]}]copied_users = deepcopy(users)copied_users[0]["tags"].append("vip")print(users) # [{'name': 'Tom', 'tags': ['admin']}]print(copied_users) # [{'name': 'Tom', 'tags': ['admin', 'vip']}]
6. 函数默认参数不要使用可变对象
这是 Python 里非常经典的坑。
defadd_tag(tag, tags=[]): tags.append(tag)return tagsprint(add_tag("python")) # ['python']print(add_tag("ai")) # ['python', 'ai']
默认参数只会在函数定义时创建一次,所以多个调用共享了同一个列表。
推荐写法:
defadd_tag(tag, tags=None):if tags isNone: tags = [] tags.append(tag)return tags
7. 遍历列表时不要直接删除元素
一边遍历一边删除列表元素,可能导致部分元素被跳过。
numbers = [1, 2, 3, 4, 5, 6]for number in numbers:if number % 2 == 0: numbers.remove(number)print(numbers)
推荐使用列表推导式生成新列表:
numbers = [1, 2, 3, 4, 5, 6]numbers = [number for number in numbers if number % 2 != 0]print(numbers) # [1, 3, 5]
这类写法更清晰,也更符合 Python 风格。
8. 字典取值推荐使用 get 和 setdefault
直接访问不存在的 key 会抛出 KeyError:
user = {"name": "Tom"}print(user["age"]) # KeyError
如果 key 可能不存在,使用 get:
age = user.get("age", 0)print(age)
如果希望 key 不存在时初始化一个默认值,可以使用 setdefault:
groups = {}groups.setdefault("python", []).append("Tom")groups.setdefault("python", []).append("Alice")print(groups) # {'python': ['Tom', 'Alice']}
不过复杂分组逻辑里,更推荐使用 collections.defaultdict。
from collections import defaultdictgroups = defaultdict(list)groups["python"].append("Tom")groups["python"].append("Alice")
❝代码仓库:
https://github.com/ibarryyan/golang-tips-100