目录
Python 星号 * 的 6 大用法全解析:从乘法到解包,一篇就够!
在 Python 里,星号
*和双星号**堪称最灵活、最容易被低估的语法元素之一。它们既能做数学运算,又能玩花式解包;既能定义可变参数函数,也能在函数调用时“一键打散”列表和字典。
今天这篇文章,我们就用 “场景 + 代码 + 运行结果” 的方式,把星号的所有用法一次性讲透。看完保证让你在日常编码时少写 30% 的胶水代码!
📌 目录
- 数学运算:乘法与幂
- 序列重复 & 拼接
- 函数定义:
*args与**kwargs - 函数调用:实参解包
- 并行赋值与剩余元素收集
- PEP 448:字面量中的扩展解包
- 思维导图 & 小结
1️⃣ 数学运算:乘法与幂
最“原始”的用法就是在 数值类型 上做二元运算:
| 运算符 | 功能 | 示例 | 结果 |
|---|---|---|---|
* | 乘法 | 7 * 3 | 21 |
** | 幂运算 | 2 ** 10 | 1024 |
>>> 7 * 3
21
>>> 2 ** 10
1024
2️⃣ 序列重复 & 字符串/列表拼接
2.1 重复(Repeat)
任何序列类型(str、list、tuple、bytes、bytearray)都可以被 * 重复:
>>> '-' * 30 # 字符串
'------------------------------'
>>> [0] * 5 # 列表
[0, 0, 0, 0, 0]
>>> (1,) * 4 # 元组
(1, 1, 1, 1)
>>> b'a' * 3 # bytes
b'aaa'
2.2 解包拼接(Unpack & Merge)
借助 * 的解包能力,可以优雅地合并多个序列:
>>> a = [1, 2]
>>> b = [3, 4]
>>> [*a, *b, 5] # 列表合并
[1, 2, 3, 4, 5]
>>> (*a, *b) # 元组合并
(1, 2, 3, 4)
>>> {*a, *b, 5} # 集合自动去重
{1, 2, 3, 4, 5}
3️⃣ 函数定义:*args 与 **kwargs
在函数形参列表里:
| 语法 | 收集类型 | 结果类型 | 说明 |
|---|---|---|---|
*args | 位置参数 | tuple | 多余的位置参数被打包成元组 |
**kwargs | 关键字参数 | dict | 多余的关键字参数被打包成字典 |
3.1 基础示例
def demo(a, b=0, *args, **kwargs):
print('a :', a)
print('b :', b)
print('*args :', args, type(args))
print('**kwargs:', kwargs, type(kwargs))
# 调用
demo(1, 2, 3, 4, x=5, y=6)
运行结果:
a : 1
b : 2
*args : (3, 4) <class 'tuple'>
**kwargs: {'x': 5, 'y': 6} <class 'dict'>
3.2 仅限关键字参数(Keyword-Only)
在 * 后再定义形参,这些形参只能通过关键字传入:
def create_user(name, *, age, email):
# age 和 email 必须显式指定关键字
pass
create_user('Alice', age=18, email='a@b.com') # ✅
create_user('Alice', 18, 'a@b.com') # ❌ TypeError
4️⃣ 函数调用:实参解包
如果你已经有一个列表/元组/字典,想把它“打散”成位置参数或关键字参数,可以在调用时前置 * / **:
4.1 位置参数解包
def add(x, y, z):
return x + y + z
nums = [1, 2, 3]
print(add(*nums)) # 6,等价于 add(1, 2, 3)
4.2 关键字参数解包
config = {'host': '127.0.0.1', 'port': 3306, 'user': 'root'}
def connect(host, port, user, password=''):
print(f'{user}@{host}:{port} pwd={password!r}')
connect(**config, password='123456')
# root@127.0.0.1:3306 pwd='123456'
4.3 混用 * 与 **
args = (1, 2)
kwargs = {'c': 3, 'd': 4}
def foo(a, b, c, d):
return a + b + c + d
foo(*args, **kwargs) # 10
5️⃣ 并行赋值与剩余元素收集(PEP 3132)
5.1 收集剩余元素
在赋值语句左侧使用 *变量名,可将“剩余”元素打包成列表:
first, *middle, last = range(5)
print(first) # 0
print(middle) # [1, 2, 3]
print(last) # 4
5.2 忽略占位
惯用法:用下划线 _ 或 * 占位,提高可读性:
username, _, uid, *extras = 'root:x:0:0:root:/root:/bin/bash'.split(':')
print(username, uid, extras)
# root 0 ['0', 'root', '/root', '/bin/bash']
6️⃣ PEP 448:字面量中的扩展解包(Python 3.5+)
从 Python 3.5 起,允许在列表、集合、字典字面量中“就地展开”:
6.1 列表/集合字面量
l1 = [1, 2]
l2 = [3, 4]
merged = [*l1, 'hi', *l2, 5]
print(merged) # [1, 2, 'hi', 3, 4, 5]
s = {*l1, *l2, 5}
print(s) # {1, 2, 3, 4, 5}
6.2 字典字面量
defaults = {'debug': False, 'port': 8000}
custom = {'port': 9000, 'ssl': True}
final = {**defaults, **custom, 'host': '0.0.0.0'}
print(final)
# {'debug': False, 'port': 9000, 'ssl': True, 'host': '0.0.0.0'}
7️⃣ 思维导图 & 一张图总结
由于平台限制,这里用文本表示:
* 的六大场景
├─ 数学运算
│ ├─ a * b
│ └─ a ** b
├─ 序列重复
│ ├─ '-' * 30
│ └─ [0] * 5
├─ 函数定义
│ ├─ *args
│ └─ **kwargs
├─ 函数调用
│ ├─ foo(*lst)
│ └─ foo(**dict)
├─ 并行赋值
│ ├─ a, *b, c = seq
│ └─ head, *_, tail = seq
└─ 扩展解包
├─ [*a, *b]
└─ {**d1, **d2}
🎁 总结 & 建议
| 场景 | 推荐写法 | 避免 |
|---|---|---|
| 合并列表 | [*a, *b] | a + b(可读性略差) |
| 函数参数 | def f(a, *args, **kw) | def f(a, l=[])(可变默认参数坑) |
| 忽略多余元素 | *_, last = seq | 切片 seq[-1](不够通用) |
一句话记忆:
在“表达式”里,*用来 拆开 或 重复;
在“函数”里,*用来 收集 或 打散;
在“赋值”里,*用来 打包剩余。
如果你觉得本文对你有帮助,点个赞 👍、收藏 ⭐、转发 ↗️ 支持一下吧!
更多 Python 黑魔法,欢迎关注我的博客。
1万+

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



