前面讨论了如果一个字典中有“键”找不到,共有四种解决方式。 这四种办法中,get 方案要胜过利用 in 表达式 KeyError 异常来解决的那两种方案,对于某些用例,我们可能觉得 setdefault 应该是代码最简短的办法。

总结

  • 如果你管理的字典可能需要添加任意的键,那么应该考虑能否用内置的 collections 模块中的 defaultdict 实例来解决问题。
  • 如果这种键名比较随意的字典是别人传给你的,你无法把它创建成 defaultdict, 那么应该考虑通过 get 方法访问其中的键值。在个别情况下,也可以考虑改用 setdefault 方法,因为那样写更短。

    对于 get 方式 - 比较 setdefault

    例如,笔者要记录自己去过哪些国家,还要记录在每个国家到过哪些城市。那可以用这样一个字典,把国名与包含城市名称的集(set)关联起来。

  1. visits = {
  2. 'Mexico': {'Tulum', 'Puerto Vallarta'},
  3. 'Japan': {'Hakone'},
  4. }
  • 通过 setdefault 方案把新的城市添加到对应的集里,
  • 这要比利用 get 方法与赋值表达式(Python 3.8 的新特性)来实现的方案短很多。 ```python visits.setdefault(‘France’, set()).add(‘Arles’) # Short

if (japan := visits.get(‘Japan’)) is None: # Long,这里有赋值表达式 visits[‘Japan’] = japan = set()

japan.add(‘Kyoto’)

print(visits)

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22011425/1648004671101-156a3316-6fad-4536-b029-8d9a5c009ab8.png#clientId=u1e7d4d68-ca91-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=192&id=ua379cace&margin=%5Bobject%20Object%5D&name=image.png&originHeight=192&originWidth=564&originalType=binary&ratio=1&rotation=0&showTitle=false&size=49893&status=done&style=none&taskId=u9c1bb0a0-9571-42c2-9ea7-976f8e2545a&title=&width=564)
  2. <a name="Tzhgd"></a>
  3. # 封装类 - setdefault 方法
  4. - 对于上面的问题,写一个类
  5. ```python
  6. class Visits:
  7. def __init__(self):
  8. self.data = {}
  9. def add(self, country, city):
  10. city_set = self.data.setdefault(country, set())
  11. city_set.add(city)
  12. # 调用
  13. visits = Visits()
  14. visits.add('Russia', 'Yekaterinburg')
  15. visits.add('Tanzania', 'Zanzibar')
  16. print(visits.data)

image.png

  • 用 setdefault 不够高效,因为无论 country 在不在 字典里,都会创建一个新的 set 实例
  • 而且 setdefault 不怎么好理解

    封装类 - defaultset 方法

  • 在键缺失的情况下,自动添加这个键以及键所对应的默认值 ```python from collections import defaultdict

class Visits: def init(self): self.data = defaultdict(set) def add(self, country, city): self.data[country].add(city)

visits = Visits() visits.add(‘England’, ‘Bath’) visits.add(‘England’, ‘London’) print(visits.data) ``` image.png

  • 这种任务用 defaultdict 实现要比用 setdefault 好得多
  • 节省开销