Python高级编程(28):dict的子类
python中一切都可以被继承,dict自然不例外,但是我们并不建议大家去继承Python中的内置的像list,dict等数据结构,特别是用C语言写的数据结构,因为有些操作不会生效。
1. 自定义一个字典时,不要直接继承自dict,因为有些操作会不生效
1 | class MyDict(dict): |
也就是是说在某些情况下,用C语言写的Python内置的数据结构并不会去调用我们覆盖的方法,即方法重写失败,因此想要避免这个问题,可以继承collections模块的UserDict。
2、使用继承UserDict的方式来实现自定义的字典
1 | from collections import UserDict |
我们可以对比一下,C语言写的dict中的__setitem__
魔法函数,和用Python写的collections模块中UserDict的魔法函数__setitem__
的区别:
C语言写的dict中的__setitem__
魔法函数:
1 | def __setitem__(self, *args, **kwargs): # real signature unknown |
Python写的collections模块中UserDict的__setitem__
魔法函数:
1 | def __setitem__(self, key, item): |
这两者是有区别的。
3、创建带有默认值的字典,使用collections模块中的defaultdict
这里主要介绍defaultdict的实现原理,字典之所以可以实现带有默认值,因为它内部实现了__missing__
这个魔法方法,在UserDict类里面的__getitem__
方法会调用__missing__
方法。
我们查看一下UserDict的源码,发现先判断key是否存在data中,不存在则判断是否具有__missing__
魔法函数,而defaultdict其实就是重写了__missing__
魔法函数这个魔法函数:
1 | def __getitem__(self, key): |
查看collections模块中的defaultdict的源码,发现它确实重写了__missing__
这个魔法函数:
1 | def __missing__(self, key): # real signature unknown; restored from __doc__ |
而且,若key不存在,则会调用这个default_factory()方法,查看一下它的源码:
1 | default_factory = property(lambda self: object(), lambda self, v: None, lambda self: None) # default |
它会将这个值赋值给对象,property这个属性方法会在后面的元类编程中介绍。
1 | from collections import defaultdict |