Python 切片赋值 vs 普通赋值:你真的改了那个 list 吗?

一句话结论

python 复制代码
a = new_list      # 换指针:a 指向新对象,原对象不变
a[:] = new_list   # 换内容:原对象被就地修改,所有引用者同步看到变化

1. 问题场景

你写了一个函数,想在内部"替换"传进来的 list:

python 复制代码
def compress(messages):
    summary = summarize(messages)
    messages = [summary]  # ← 这行有效吗?

history = [msg1, msg2, msg3, ...]
compress(history)
print(history)  # 还是 [msg1, msg2, msg3, ...] !没变!

为什么?因为 Python 函数参数是引用传递 ,但 = 赋值只改变局部变量的指向,不影响外部。


2. 内存模型图解

普通赋值 messages = new_list

css 复制代码
调用前:
  history ──────┐
                ▼
  messages ───► [msg1, msg2, msg3]    ← 同一个对象

赋值后:
  history ──────► [msg1, msg2, msg3]  ← 原对象,没人动它
  messages ────► [summary]            ← 新对象,局部变量换了指向

函数结束,messages 局部变量销毁,[summary] 被 GC 回收。history 纹丝不动。

切片赋值 messages[:] = new_list

bash 复制代码
调用前:
  history ──────┐
                ▼
  messages ───► [msg1, msg2, msg3]    ← 同一个对象

赋值后:
  history ──────┐
                ▼
  messages ───► [summary]             ← 同一个对象,内容被替换了!

[:] 是对对象本身动手术------清空原内容、填入新内容,对象 id 不变。


3. 验证:id 不变 vs id 变了

python 复制代码
a = [1, 2, 3]
print(id(a))       # 4398046208

# 普通赋值
a = [4, 5, 6]
print(id(a))       # 4398100032  ← id 变了!新对象

# 切片赋值
a = [1, 2, 3]
print(id(a))       # 4398046208
a[:] = [4, 5, 6]
print(id(a))       # 4398046208  ← id 没变!同一个对象

4. 切片赋值的几种形式

语法 含义 等价操作
a[:] = x 替换全部内容 a.clear(); a.extend(x)
a[1:3] = x 替换索引 1、2 的元素 删掉旧的,插入新的
a[::2] = x 替换偶数位置 要求 len(x) 匹配
a[:0] = x 在开头插入 a = x + a 的就地版
a[len(a):] = x 在末尾追加 a.extend(x)
python 复制代码
a = [0, 1, 2, 3, 4]
a[1:3] = [10, 20, 30]     # 可以长度不等!
print(a)                  # [0, 10, 20, 30, 3, 4]

5. 常见陷阱

陷阱 1:tuple 没有切片赋值

python 复制代码
t = (1, 2, 3)
t[:] = (4, 5, 6)  # TypeError: 'tuple' object does not support item assignment

tuple 是不可变的,只能 t = new_tuple。

陷阱 2:dict 没有切片

python 复制代码
d = {"a": 1}
d[:] = {"b": 2}  # TypeError
# dict 的就地替换用:
d.clear()
d.update(new_dict)

陷阱 3:步长切片赋值长度必须匹配

python 复制代码
a = [0, 1, 2, 3, 4]
a[::2] = [10, 20, 30]    # ✅ 3个位置(0,2,4)对应 3个值
a[::2] = [10, 20]        # ❌ ValueError: attempt to assign sequence of size 2
                         #    to extended slice of size 3

6. 一图总结

css 复制代码
┌─────────────────────────────────────────────────┐
│              普通赋值 a = x                       │
│  • 局部变量换指向                                  │
│  • 原对象不变                                     │
│  • 其他引用者看不到变化                             │
│  • id(a) 变了                                    │
├─────────────────────────────────────────────────┤
│              切片赋值 a[:] = x                     │
│  • 原对象被就地修改                                │
│  • 所有引用者同步看到                              │
│  • id(a) 不变                                    │
│  • 适用于需要"通过参数修改调用方数据"的场景          │
└─────────────────────────────────────────────────┘

记忆口诀

= 换人,[:] 换心。

普通赋值换了一个人(新对象),切片赋值换了心(原对象内容变了,人还是那个人)。

相关推荐
全栈练习生10 小时前
AI Agent 沙箱
python·ai
SEO_juper11 小时前
用 Python 写一个 GEO 可见性检查脚本:你的网站现在能被 AI 引用吗
开发语言·人工智能·爬虫·python·seo·外贸独立站
用户83562907805112 小时前
使用 Python 对 Excel 工作表进行排序
后端·python
for_ever_love__12 小时前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram
用户83562907805113 小时前
使用 Python 合并 PowerPoint 演示文稿
后端·python
weixin_4617694013 小时前
VS Code 中创建 Jupyter 文件(.ipynb)
ide·python·jupyter
2601_9669496513 小时前
多市场量化策略的数据接口应该如何设计:从数据层架构到策略接入
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
全栈弄潮儿13 小时前
Python实战第1期:Python环境搭建与第一个程序
python
心易行者13 小时前
Agent应用+API端点商业化进阶实战:从单体智能体到可付费调用的API全流程
运维·服务器·人工智能·python·apache
weixin1997010801614 小时前
《1688图片空间API踩坑:img.upload 与 album.* 的防盗链与CDN缓存问题》(附Python源码)
开发语言·python·缓存