当前位置:首页>python>Python 字典拆包操作详解

Python 字典拆包操作详解

  • 2026-10-10 16:06:14
Python 字典拆包操作详解

字典拆包核心符号:*、**

  • *dict:拆出字典的键,多用于序列接收、函数位置参数
  • **dict:拆出键值对,多用于函数关键字传参、字典合并

一、基础概念回顾

字典:d = {"name":"张三", "age":18, "gender":"男"}

  1. 直接遍历字典,默认只取key
d = {"name":"张三", "age":18}
for item in d:
    print(item)  # name age
  1. * 单星拆包字典 → 仅提取所有键
  2. ** 双星拆包字典 → 拆解成 key=value 形式

一、单星号 * 字典拆包(拆键)

1. 场景1:列表/元组解包、合并序列

d = {"a": 1, "b": 2, "c": 3}

# 把字典所有key拆开放入列表
lst = [*d]
print(lst)  # ['a', 'b', 'c']

# 元组
t = (*d,)
print(t)  # ('a', 'b', 'c')

# 多个字典合并键集合
d1 = {"x":1, "y":2}
d2 = {"y":99, "z":3}
keys = [*d1, *d2]
print(keys)  # ['x', 'y', 'y', 'z']

2. 场景2:函数可变位置参数 *args

函数 *args 接收零散位置参数,字典用 *d 传入会自动拆所有key:

deffunc(*args):
    print(args)

d = {"name":"李四", "score":90}
func(*d)  # 等价于 func("name", "score")
# 输出:('name', 'score',)

3. 场景3:zip、print 等批量传参

d = {"k1":10, "k2":20}
print(*d)  # print("k1", "k2")
# 输出:k1 k2

限制:*d 只能提取键,拿不到值;如果要同时拆键值对,用 d.items():

d = {"a":1, "b":2}
print(*d.items())
# 输出:('a', 1) ('b', 2)

二、双星号 ** 字典拆包(拆键值对,最常用)

**d 会将字典拆解为 key=value 的关键字参数形式,不能单独赋值给变量,只能用在:函数传参、字典合并。

1. 场景1:函数关键字参数传参(高频用法)

示例1:普通函数接收关键字

defuser_info(name, age, gender):
    print(f"姓名:{name},年龄:{age},性别:{gender}")

# 原始传参
user_info(name="王五", age=20, gender="男")

# 字典存储参数,**拆包一键传入
user = {"name":"王五", "age":20, "gender":"男"}
user_info(**user)
# 等价于 user_info(name="王五", age=20, gender="男")

示例2:函数可变关键字参数 **kwargs

defshow_data(**kwargs):
    print("接收的所有键值对:", kwargs)

data = {"id":1001, "title":"Python教程", "price":29.9}
show_data(**data)
# 输出:接收的所有键值对:{'id': 1001, 'title': 'Python教程', 'price': 29.9}

示例3:混合普通参数、*args、**kwargs

defdemo(a, b, *args, **kwargs):
    print(a, b)
    print(args)
    print(kwargs)

d = {"x":10, "y":20}
demo(1, 2, 3, 4, **d)
# 输出
# 1 2
# (3, 4)
# {'x': 10, 'y': 20}

2. 场景2:字典合并、拷贝(Python3.5+)

方式1:使用 {**d1, **d2} 合并字典

规则:后面字典的同名键会覆盖前面的值

d1 = {"name":"小明", "age":16}
d2 = {"age":17, "gender":"男"}

new_d = {**d1, **d2}
print(new_d)
# {'name': '小明', 'age': 17, 'gender': '男'}

方式2:基于原字典新增/修改字段

student = {"name":"小红", "cls":"一班"}
# 复制原字典,同时新增/覆盖age
new_stu = {**student, "age":15}
print(new_stu)
# {'name': '小红', 'cls': '一班', 'age': 15}

对比 update()

# update 原地修改原字典,会改变原有数据
student.update({"age":15})
# {**d1,**d2} 会生成全新字典,不修改原数据

3. 禁止用法:** 不能单独用于变量赋值

d = {"a":1, "b":2}
x = **d  # 直接报错!语法不允许

** 只能出现在 {} 字典字面量、函数调用传参两处。


三、字典 items / keys / values 拆包补充

1. 拆包 items() 键值对

d = {"a": 100, "b": 200}
# 单星拆包 items,得到多个元组
print(*d.items())  # ('a', 100) ('b', 200)

# 循环拆包 k,v
for k, v in d.items():
    print(k, v)

2. 拆包 values() 获取所有值

d = {"a":1, "b":2}
val_list = [*d.values()]
print(val_list)  # [1, 2]

3. 拆包 keys() 和直接 *d 完全等价

[*d] == [*d.keys()]  # True

四、实战综合案例

案例1:接口参数拼接(爬虫/API常用)

base_params = {"appid": "123456", "timestamp": 1780000000}
extra = {"keyword": "python", "page": 1}

# 合并所有请求参数
request_params = {**base_params, **extra}
print(request_params)
# {'appid': '123456', 'timestamp': 1780000000, 'keyword': 'python', 'page': 1}

案例2:类初始化批量传参

classBook:
def__init__(self, name, author, price):
        self.name = name
        self.author = author
        self.price = price

book_info = {"name":"Python入门", "author":"张三", "price":39.8}
# 字典拆包快速实例化
book = Book(**book_info)
print(book.name, book.author)  # Python入门 张三

案例3:函数缺省参数 + 字典覆盖

defprint_goods(name, stock=0, price=0):
    print(f"{name} 库存:{stock} 价格:{price}")

# 默认参数
print_goods("水杯")

# 用字典覆盖部分默认参数
goods = {"name":"键盘", "price":99}
print_goods(**goods)
# 输出:键盘 库存:0 价格:99

五、单星 * 和双星 ** 字典拆包对比总结

符号
作用对象
拆解内容
可用场景
限制
*d
字典本身
所有 key
列表/元组、*args、print、zip
只能拿到键,无法拆值
*d.items()
字典键值对
(k,v)元组序列
循环、序列拼接
无键值对拆分传参能力
**d
字典本身
key=value 关键字
函数传参、字典合并{}
不能单独赋值,只能用于传参/字典字面量

关键记忆点

  1. 想要提取所有键:用 *字典
  2. 想要拆解键值对传给函数:用 **字典
  3. 想要合并多个字典:{**d1, **d2}
  4. ** 不能写在等号右侧单独赋值,会语法报错

拓展:Python3.9+ 管道合并字典(|)补充

除 {**d1,**d2} 外,新版本支持 | 合并字典,效果一致:

d1 = {"a":1}
d2 = {"b":2}
new_d = d1 | d2
print(new_d)  # {'a': 1, 'b': 2}

但管道运算符无法在函数传参时替代 **,拆包传参仍必须用 **。

最新文章

随机文章