collections 模块还提供了 defaultdict,它和字典相似,不同的是,如果你访问一个不存在的键,它会自动创建一个新值。
创建一个 defaultdict 对象时,需要提供一个用于创建新值的函数。用来创建对象的函数有时候被称为工厂(factory)函数。用于创建列表、集合以及其他类型对象的内置函数,都可以用作工厂函数:
示例代码请注意,参数 list(是一个类对象),而不是 list()(一个新的列表)。你提供的函数直到访问不存在的键时,才会被调用:
访问不存在的键新列表 t 也会加到字典中。所以,如果我们修改 t,改动也会在 d 中体现:
修改 t,改动也会在 d 中体现如果创建一个由列表组成的字典,使用 defaultdict 往往能够帮助我们写出更简洁的代码。例如,我们创建一个字典,将排序的字面字符串映射到可以由那些字母拼写出来的单词列表。例如,‘opst’映射到列表['opts', 'post', 'pots', 'spot', 'stop', 'tops']。下面是原始的代码:
def all_anagrams(filename):
d = {}
for line in open(filename):
word = line.strip().lower()
t = signature(word)
if t not in d:
d[t] = [word]
else:
d[t].append(word)
return d
这个函数可以用 setdefault 简化:
def all_anagrams(filename):
d = {}
for line in open(filename):
word = line.strip().lower()
t = signature(word)
# if t not in d:
# d[t] = [word]
# else:
# d[t].append(word)
d.setdefault(t, []).append(word)
return d
但这个解决方案有一个缺点,它不管是否需要,每次都会创建一个列表。对于列表来说,这并不算大问题,但如果工厂函数非常复杂,就可能成为问题。
我们可以使用 defaultdict 来避免这个问题,并进一步简化代码:
def all_anagrams(filename):
# d = {}
# for line in open(filename):
# word = line.strip().lower()
# t = signature(word)
# # if t not in d:
# # d[t] = [word]
# # else:
# # d[t].append(word)
# d.setdefault(t, []).append(word)
# return d
d = defaultdict(list)
for line in open(filename):
word = line.strip().lower()
t = signature(word)
d[t].append(word)
return d
本文参考自《像计算机科学家一样思考Python (第2版)》
网友评论