Python 的 dict.fromkeys 的坑

Python 的 dict.fromkeys 的坑

Mar 10, 2023
Python

目前使用到 dict.fromkeys 方法主要有两个场景:一个是按照数组的原有顺序去重,另一个就是正常的根据 keys 构建一个 dict,这里讨论的是第二种情况。

下面这个例子:

l = ["foo", "bar"]
v = {"age": 0}

d = dict.fromkeys(l, v)

d["foo"]["age"] += 1
d["bar"]["age"] += 1

d["foo"]["age"]

由于 Python 在 v 处存储的是引用而不是值的原因,故 d["foo"]["age"] 最终的值为 2,如果用 id() 方法打印两个对象的地址,可以发现是同一个值。

print(id(d["foo"]["age"]))
print(id(d["bar"]["age"]))

# 140648770627920
# 140648770627920

要解决这个问题,可以适当改一下写法,不使用 fromkeys() 或者避免在 fromkeys 的参数里设置一个引用类型的对象,不然的话属于高危操作了,需要格外注意使用时的场景。

Python 中属于引用类型的对象包括:

  1. 列表 (list):列表是一种可变序列类型,可以包含任何类型的数据。列表通过 [] 方括号包围,元素之间用逗号分隔。
  2. 元组 (tuple):元组是一种不可变序列类型,可以包含任何类型的数据。元组通过 () 圆括号包围,元素之间用逗号分隔。
  3. 集合 (set):集合是一种无序且不重复的集合类型,可以包含任何类型的数据。集合通过 {} 大括号包围,元素之间用逗号分隔。
  4. 字典 (dict):字典是一种键值对的映射类型,可以包含任何类型的键和值。字典通过 {} 大括号包围,键值对之间用冒号分隔,每个键值对之间用逗号分隔。
  5. 类 (class):类是一种面向对象的数据类型,可以包含任何属性和方法。
  6. 函数 (function):函数是一种可调用对象,可以包含任何代码逻辑。函数可以接受参数并返回值。

除了引用类型,Python 还有以下类型:

  1. 数值型 (Numeric):包括整数 (int)、浮点数 (float)、复数 (complex)。
  2. 布尔型 (Boolean):包括 True 和 False 两个值,用于表示逻辑真和逻辑假。
  3. 字符串 (String):字符串是一种不可变序列类型,用于表示文本数据。
  4. 字节串 (Bytes):字节串是一种不可变序列类型,用于表示二进制数据。
  5. 字节数组 (Bytearray):字节数组是一种可变序列类型,用于表示二进制数据。
  6. 空值 (NoneType):None 是一个特殊的值,用于表示空值或缺失值。
本文共 801 字,上次修改于 Apr 5, 2023,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» 使用 Django 查询数据库的分表

» Django 中 N+1 查询问题优化

» Django 的中间件执行顺序

» Django 的软删除设计

» 浅谈 Django-REST-Framework 的设计与源码