fromkeys() 是什么?
fromkeys() 是 Python 字典(dict)的一个类方法(class method),用于创建一个新的字典。

它的主要作用是:使用一个可迭代对象(如列表、元组等)作为键,为这些键创建一个新字典,并给所有键设置一个统一的默认值。
语法
dict.fromkeys() 有两种形式:
使用 dict 直接调用(最常用)
new_dict = dict.fromkeys(keys_sequence, value)
通过字典实例调用(不常用,效果相同)
my_dict = {}
new_dict = my_dict.fromkeys(keys_sequence, value)
参数说明:
keys_sequence(必需): 一个可迭代对象,例如列表、元组、集合等,它的每个元素将成为新字典的一个键。value(可选): 新字典中所有键对应的值,如果省略此参数,默认值为None。
使用示例
示例 1:提供键和默认值
这是最常见的用法,为所有键设置一个非 None 的默认值。

# 使用列表作为键的来源
keys = ['name', 'age', 'city']
default_value = 'Unknown'
# 创建新字典
user_info = dict.fromkeys(keys, default_value)
print(user_info)
# 输出: {'name': 'Unknown', 'age': 'Unknown', 'city': 'Unknown'}
示例 2:省略默认值(默认为 None)
如果不提供第二个参数,所有键的值都会被自动设置为 None。
keys = ['a', 'b', 'c']
# 创建新字典,值默认为 None
letters = dict.fromkeys(keys)
print(letters)
# 输出: {'a': None, 'b': None, 'c': None}
示例 3:使用元组或集合作为键的来源
fromkeys() 可以接受任何可迭代对象。
# 使用元组
keys_tuple = (1, 2, 3)
numbers = dict.fromkeys(keys_tuple, 0)
print(numbers)
# 输出: {1: 0, 2: 0, 3: 0}
# 使用集合
keys_set = {'apple', 'banana', 'cherry'}
fruits = dict.fromkeys(keys_set, 'in stock')
print(fruits)
# 输出: {'cherry': 'in stock', 'apple': 'in stock', 'banana': 'in stock'}
# (集合是无序的,所以键的顺序可能不固定)
⚠️ 重要注意事项(尤其是可变对象)
这是 fromkeys() 最容易出错的地方,也是面试中经常被问到的点。
核心问题: 当 value 参数是一个可变对象(如列表、字典)时,所有键会共享同一个对象实例,这意味着,修改其中一个键对应的值,会影响所有其他键。
示例 4:错误使用 - 共享可变对象
keys = ['a', 'b', 'c']
# 错误:使用列表作为默认值
default_list = ['default_value']
my_dict = dict.fromkeys(keys, default_list)
print("初始字典:", my_dict)
# 输出: 初始字典: {'a': ['default_value'], 'b': ['default_value'], 'c': ['default_value']}
# 现在我们修改 'a' 对应的列表
my_dict['a'].append('new_item')
print("修改后的字典:", my_dict)
# 输出: 修改后的字典: {'a': ['default_value', 'new_item'], 'b': ['default_value', 'new_item'], 'c': ['default_value', 'new_item']}
为什么会这样?
dict.fromkeys(keys, default_list)这行代码只创建了一个列表对象['default_value']。- 在新字典
my_dict中,键'a','b','c'所对应的不是列表的副本,而是同一个列表的引用。 - 当执行
my_dict['a'].append('new_item')时,我们通过引用找到了这个唯一的列表,并向它添加了一个元素。 - 因为
'b'和'c'也指向同一个列表,所以它们看到的列表也被修改了。
示例 5:正确做法 - 创建独立的对象
如果你希望每个键对应的值都是独立的,应该在循环中逐个创建对象,而不是使用 fromkeys()。
keys = ['a', 'b', 'c']
my_dict = {}
for key in keys:
# 每次循环都创建一个新的、独立的列表
my_dict[key] = ['default_value']
print("初始字典:", my_dict)
# 输出: 初始字典: {'a': ['default_value'], 'b': ['default_value'], 'c': ['default_value']}
# 现在我们修改 'a' 对应的列表
my_dict['a'].append('new_item')
print("修改后的字典:", my_dict)
# 输出: 修改后的字典: {'a': ['default_value', 'new_item'], 'b': ['default_value'], 'c': ['default_value']}
这次,修改 'a' 的值不会影响 'b' 和 'c',因为它们是三个独立的列表对象。
| 特性 | 描述 |
|---|---|
| 功能 | 从一个键的序列创建一个新字典,并为所有键设置统一的默认值。 |
| 语法 | dict.fromkeys(keys_sequence, value=None) |
| 优点 | 代码简洁,可以快速初始化一个字典。 |
| 核心陷阱 | 当 value 是可变对象(如 list, dict)时,所有键会共享该对象的引用,导致修改一个影响全部。 |
| 最佳实践 | 如果默认值是可变对象,不要直接在 fromkeys() 中使用它,应改用循环为每个键创建独立的对象实例。 |
fromkeys() 是一个强大的初始化工具,但在使用可变对象作为默认值时一定要格外小心。
