对于一些场景, 我们要求词典对于不存在的key,不报错,返回默认值。
dict有处理方法, get 方法 或者 setdefault方法。
但是过于繁琐。
https://realpython.com/python-defaultdict/#handling-missing-keys-in-dictionaries
dict有处理方法对缺失key的处理。
A common issue that you can face when working with Python dictionaries is how to handle missing keys. If your code is heavily based on dictionaries, or if you’re creating dictionaries on the fly all the time, then you’ll soon notice that dealing with frequent
KeyError
exceptions can be quite annoying and can add extra complexity to your code. With Python dictionaries, you have at least four available ways to handle missing keys:
- Use
.setdefault()
- Use
.get()
- Use the
key in dict
idiom- Use a
try
andexcept
block
setdefault(key[, default])
If
key
is in the dictionary, return its value. If not, insertkey
with a value ofdefault
and returndefault
.default
defaults toNone
.
get(key[, default])
Return the value for
key
ifkey
is in the dictionary, elsedefault
. Ifdefault
is not given, it defaults toNone
, so that this method never raises aKeyError
.
>>> a_dict = {} >>> a_dict['missing_key'] Traceback (most recent call last): File "<stdin>", line 1, in <module> a_dict['missing_key'] KeyError: 'missing_key' >>> a_dict.setdefault('missing_key', 'default value') 'default value' >>> a_dict['missing_key'] 'default value' >>> a_dict.setdefault('missing_key', 'another default value') 'default value' >>> a_dict {'missing_key': 'default value'}
defaultdict
Typecollection库的defaultdict是dict的一个子类
在defaultdict初始化方法中,设置缺失元素的创建方法, 此创建方法,存储在 default_factory属性。
The Python standard library provides
collections
, which is a module that implements specialized container types. One of those is the Pythondefaultdict
type, which is an alternative todict
that’s specifically designed to help you out with missing keys.defaultdict
is a Python type that inherits fromdict
:
>>> from collections import defaultdict >>> issubclass(defaultdict, dict) True
The main difference between
defaultdict
anddict
is that when you try to access or modify akey
that’s not present in the dictionary, a defaultvalue
is automatically given to thatkey
. In order to provide this functionality, the Pythondefaultdict
type does two things:
- It overrides
.__missing__()
.- It adds
.default_factory
, a writable instance variable that needs to be provided at the time of instantiation.The instance variable
.default_factory
will hold the first argument passed intodefaultdict.__init__()
. This argument can take a valid Python callable orNone
. If a callable is provided, then it’ll automatically be called bydefaultdict
whenever you try to access or modify the value associated with a missing key.
>>> # Correct instantiation >>> def_dict = defaultdict(list) # Pass list to .default_factory >>> def_dict['one'] = 1 # Add a key-value pair >>> def_dict['missing'] # Access a missing key returns an empty list [] >>> def_dict['another_missing'].append(4) # Modify a missing key >>> def_dict defaultdict(<class 'list'>, {'one': 1, 'missing': [], 'another_missing': [4]})
defaultdict
Type用户可以定义满足自己需求的 defaultdict 类
这样方法的好处是, 用户可以在 __missing__ 方法中进行定制缺失处理逻辑。
例如对于缺失的key的默认值返回key小写形式,或者按照key的默认值表来返回默认值。
In this section, you’ll be coding a Python class that will behave much like a
defaultdict
. To do that, you’ll subclasscollections.UserDict
and then add.__missing__()
. Also, you need to add an instance attribute called.default_factory
, which will hold the callable for generating default values on demand. Here’s a piece of code that emulates most of the behavior of the Pythondefaultdict
type:
import collections class my_defaultdict(collections.UserDict): def __init__(self, default_factory=None, *args, **kwargs): super().__init__(*args, **kwargs) if not callable(default_factory) and default_factory is not None: raise TypeError('first argument must be callable or None') self.default_factory = default_factory def __missing__(self, key): if self.default_factory is None: raise KeyError(key) if key not in self: self[key] = self.default_factory() return self[key]
>>> from my_dd import my_defaultdict >>> dd_one = my_defaultdict(list) >>> dd_one {} >>> dd_one['missing'] [] >>> dd_one {'missing': []} >>> dd_one.default_factory = int >>> dd_one['another_missing'] 0 >>> dd_one {'missing': [], 'another_missing': 0} >>> dd_two = my_defaultdict(None) >>> dd_two['missing'] Traceback (most recent call last): File "<stdin>", line 1, in <module> dd_two['missing'] File "/home/user/my_dd.py", line 10, in __missing__ raise KeyError(key) KeyError: 'missing'