杰瑞科技汇

Python字典formkeys()如何创建键值对?

这是一个非常实用且常用的字典方法,用于快速创建一个具有默认值的字典。

Python字典formkeys()如何创建键值对?-图1
(图片来源网络,侵删)

核心概念

dict.fromkeys() 是一个类方法,这意味着你直接在字典类型 dict 上调用它,而不是在某个已存在的字典实例上调用,它的主要作用是:

使用一个可迭代对象(如列表、元组)的元素作为键,并使用一个指定的值作为所有键对应的默认值,来创建一个新字典。


方法签名

dict.fromkeys(iterable, value=None)

参数说明:

  1. iterable (必需参数): 一个可迭代对象,例如列表、元组、集合或字符串,这个可迭代对象中的每一个元素都会成为新字典中的一个
  2. value (可选参数): 一个可选的值,将作为新字典中所有键的默认值,如果不提供此参数,则默认为 None

返回值:

该方法会返回一个新创建的字典,它不会修改原始的可迭代对象。


使用示例

示例 1:基本用法(值为 None)

这是最常见的用法,当你只想创建一个键集合,并且初始值不重要时。

Python字典formkeys()如何创建键值对?-图2
(图片来源网络,侵删)
# 使用一个列表作为键的来源
keys = ['name', 'age', 'city']
new_dict = dict.fromkeys(keys)
print(new_dict)
# 输出: {'name': None, 'age': None, 'city': None}

示例 2:指定默认值

你可以为所有键提供一个统一的、非 None 的初始值。

keys = ['a', 'b', 'c']
default_value = 0
new_dict = dict.fromkeys(keys, default_value)
print(new_dict)
# 输出: {'a': 0, 'b': 0, 'c': 0}

示例 3:使用元组和集合作为键的来源

fromkeys() 方法接受任何可迭代对象。

# 使用元组
keys_tuple = ('apple', 'banana', 'cherry')
dict_from_tuple = dict.fromkeys(keys_tuple, 'in_stock')
print(f"从元组创建: {dict_from_tuple}")
# 输出: 从元组创建: {'apple': 'in_stock', 'banana': 'in_stock', 'cherry': 'in_stock'}
# 使用集合
keys_set = {100, 200, 300}
dict_from_set = dict.fromkeys(keys_set)
print(f"从集合创建: {dict_from_set}")
# 输出: 从集合创建: {100: None, 200: None, 300: None} (注意集合是无序的,所以键的顺序可能不同)

示例 4:使用字符串作为键的来源

当使用字符串时,字符串中的每一个字符都会成为一个独立的键。

char_keys = "ABC"
dict_from_string = dict.fromkeys(char_keys, "vowel")
print(dict_from_string)
# 输出: {'A': 'vowel', 'B': 'vowel', 'C': 'vowel'}

一个非常重要的注意事项:可变默认值

这是一个非常经典且容易出错的陷阱,当你提供的 value 是一个可变对象(如列表、字典)时,所有键都会共享同一个可变对象的引用。

Python字典formkeys()如何创建键值对?-图3
(图片来源网络,侵删)

这意味着,当你修改其中一个键对应的值时,其他所有键对应的值也都会被改变。

# 错误的示范:使用列表作为默认值
keys = ['user1', 'user2', 'user3']
# 创建一个字典,默认值为一个空列表
user_permissions = dict.fromkeys(keys, [])
# 现在给 user1 添加一个权限
user_permissions['user1'].append('read')
# 查看整个字典
print(user_permissions)
# 输出: {'user1': ['read'], 'user2': ['read'], 'user3': ['read']}  # user2 和 user3 也被意外修改了!

为什么会发生这种情况?

因为 dict.fromkeys(keys, []) 在内存中只创建了一个空列表 [],然后将这个列表的内存地址同时赋给了 'user1', 'user2', 和 'user3' 这三个键,无论你通过哪个键去修改这个列表,实际上都是在修改同一个对象。

如何正确地处理可变默认值?

如果你确实希望每个键都拥有一个独立的可变对象(比如一个独立的列表),你应该在创建字典后使用循环来初始化。

# 正确的示范:为每个键创建独立的列表
keys = ['user1', 'user2', 'user3']
user_permissions = {}
for key in keys:
    user_permissions[key] = []  # 为每个键创建一个新的、独立的空列表
# 现在给 user1 添加权限
user_permissions['user1'].append('read')
# 查看整个字典
print(user_permissions)
# 输出: {'user1': ['read'], 'user2': [], 'user3': []}  # 这次只有 user1 被修改了

{k: v for k in iterable} 字典推导式的比较

fromkeys() 非常简洁,但字典推导式提供了更多的灵活性,尤其是在处理可变默认值时。

场景:创建一个键值对,值为键本身的两倍

keys = [1, 2, 3]
# 使用 fromkeys (无法实现,因为 value 是固定的)
# dict.fromkeys(keys, key * 2)  # 语法错误,key 在 fromkeys 的上下文中不可用
# 使用字典推导式 (非常灵活)
dict_comp = {key: key * 2 for key in keys}
print(dict_comp)
# 输出: {1: 2, 2: 4, 3: 6}

场景:处理可变默认值

keys = ['a', 'b']
# 使用字典推导式(推荐方式,清晰且不易出错)
dict_comp_mutable = {key: [] for key in keys}
dict_comp_mutable['a'].append('hello')
print(f"推导式结果: {dict_comp_mutable}")
# 输出: 推导式结果: {'a': ['hello'], 'b': []}

总结对比:

特性 dict.fromkeys() 字典推导式
简洁性 非常简洁,一行代码 代码稍长,但非常清晰
灵活性 低,value 是固定的,不能依赖 key 高,可以在值部分使用 key 进行复杂计算
可变默认值 有陷阱,容易出错 安全,每次循环都会创建新对象
性能 对于简单的、不可变的默认值,通常更快 稍慢,但更通用

  • dict.fromkeys(iterable, value=None) 是一个快速创建字典的利器。
  • 它适用于键的来源已知,且所有键需要相同初始值的场景。
  • 最大的陷阱:当 value 是列表、字典等可变对象时,所有键会共享同一个对象引用,导致修改一个影响所有。
  • 对于需要为每个键创建独立可变对象,或者需要在值部分使用 key 进行逻辑处理的场景,字典推导式是更安全、更灵活的选择
分享:
扫描分享到社交APP
上一篇
下一篇