SDET / SWE · Technical Fundamentals

TikTok Python List 与 Tuple:可变性、嵌套对象和 Hash

区分容器槽位不可变与元素深度不可变,解释什么时候tuple能当字典key。

题目重点:区分容器槽位不可变与元素深度不可变,解释什么时候tuple能当字典key。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 讨论Python 3序列语义,CPython内存和速度差异只作实现条件,不作普遍定律。

解题路线

  1. list允许替换、插入、删除元素;tuple固定元素引用序列,不能重新绑定某个槽位。两者均可索引、切片与迭代,不应说tuple天然没有顺序。
  2. tuple内引用的对象仍可能可变。t=(items,)后items.append(1)会改变观察到的内容,tuple自身槽位没有换对象,因此不违反其不可变语义。
  3. tuple可哈希的前提是所有成员都可哈希;含list的tuple不能当dict key。list不可哈希是因为其内容可变,与“列表较慢”无关。
  4. 接口选择按语义:动态收集用list,固定记录或稳定组合键可用tuple。若记录字段多且需要名称,可用命名结构,别为了性能口号让调用方记住十几个位置。
  5. CPython list通常采用动态数组,索引O(1),尾追加摊还O(1),头插或中间移动O(n);tuple创建后长度固定。不保证tuple在所有任务、所有解释器上更快。
  6. 单元素tuple需要逗号,(x)只是括号表达式;序列拼接会新建容器,不能把不可变序列反复拼接的成本忽略。

手动走一遍

inner=[],t=(inner,);inner.append(1)后t显示([1],)。hash(t)报TypeError;(1,2)可以作为key。list转tuple只固定外层,内层list并未深冻结。

规模与取舍

索引在常见数组实现O(1),切片/转换长度k需O(k)时间空间;可变嵌套结构冻结成本按整个图计。tuple可哈希判断/计算也需访问成员,不必然O(1)。

易错点与追问

容易失分的边界

  • tuple内的list不能修改。
  • 所有tuple都可哈希。
  • (1)误当单元素tuple。

继续深挖

  • 怎样做深不可变配置?
  • 可变对象定义hash会造成什么风险?
  • 固定记录为什么可选dataclass?

技术参考

✓已复制微信号!