自定义字典简化代码解决定制需求
1.概述
在开发中字典使用频率是非常高的,python标准库的字典能够满足我们大部分的需求,对于一些特殊的需求如果使用标准库自带的字典也能实现,不过需要多些一些逻辑代码,使代码变得臃肿不易维护。因此创建自定义字典实现特殊需求更加便利,下面就来介绍下如何创建自定义字典解决实际需求。
2.自定义字典
2.1.选择UserDict基类
创建自定义字典,首先需要继承一个字典作为基类。那么选择继承哪个基类那,这里选择继承UserDict作为基类会更好。
选择从UserDict而不是从dict继承的主要原因是,后者有时会在某些方法的实现上走一些捷径,导致我们不得不在它的子类中重写这些方法,但是UserDict就不会带来这些问题。
另外一个值得注意的地方是,UserDict并不是dict的子类,但是UserDict有一个叫作data的属性,是dict的实例,这个属性实际上是UserDict最终存储数据的地方。
UserDict继承的是MutableMapping,所以继承该类后那些字典类型的方法都是从UserDict、MutableMapping和Mapping这些超类继承而来的。特别是最后的Mapping类,它虽然是一个抽象基类(ABC),但它却提供了好几个实用的方法。
2.2.解决字典获取不到键抛异常问题
使用字典获取某个key的时候,如果key不存在python会抛出异常,我们可以使用自定义字典方式改变它的行为,让他在获取不到key的时候返回一个默认值。
import collections
# 创建一个子类继承UserDict类
class StrKeyDict(collections.UserDict):
def __missing__(self, key):
# 判断当前key类型如果是str,则返回key
if isinstance(key, str):
raise KeyError(key)
# 如果key不是str则转为str类型返回
return self[str(key)]
# 这里可以放心假设所有已经存储的键都是字符串。因此,只要在self.data上查询就好
def __contains__(self, key):
return str(key) in self.data
# __setitem__会把所有的键都转换成字符串。由于把具体的实现委托给了self.data属性,这个方法写起来也不难。
def __setitem__(self, key, item):
self.data[str(key)] = item
__missing__魔法方法介绍
所有的映射类型在处理找不到的键的时候,都会牵扯到__missing__方法。这也是这个方法称作“missing”的原因。虽然基类dict并没有定义这个方法,但是dict是知道有这么个东西存在的。也就是说,如果有一个类继承了dict,然后这个继承类提供了__missing__方法,那么使用字典get方法获取key时会自动调用__getitem__魔法方法查找key,在__getitem__碰到找不到的键的时候,Python就会自动调用它,而不是抛出一个KeyError异常。