前言
Python 内置模块collections, 目标是提供各种专门的集合数据类型来解决特定的编程问题。
本系列介绍其中的数据结构特点和使用方法, 以便遇到某些特定的问题,可以找到对应的数据来处理, 达到事半功倍的效果
其他的可以参考
Python中的collections模块(一) 使用Counter,pythonic的对象计数方式
Python中的collections模块(二) 有序字典OrderedDict和链接字典ChainMap
Python中的collections模块(三) 命名元组namedtuple和双端队列deque
为什么要使用UserString,UserList,UserDict
编码中有时你需要自定义内置类型,例如字符串、列表和字典,以添加和修改某些行为。大部分时候可以直接对这些类型进行子类化来实现。
但是有的时候会发现, 子类化的实例并不像预期中那样表现, 因为Python对内置类型的设计和实现考虑到了开闭原则(对扩展开放,但对修改关闭)。
例如, 我需要创建一个在插入键时自动将键转为小写的字典。
可以通过子类化
dict并
覆盖.setitem()函数, 每次插入键时将键名转为小写:
In [1]: class LowerDict(dict):
...: def __setitem__(self, key, value):
...: key = key.lower()
...: super().__setitem__(key, value)
In [2]: data = LowerDict({'FIRST': 1, 'SECOND': 2})
In [3]: data['THIRD'] = 3
In [4]: data.update({'FOURTH': 4})
In [5]: data
Out[5]: {'FIRST': 1, 'SECOND': 2, 'third': 3, 'FOURTH': 4}
可以看到,只有使用 [ ] 为字典赋值时的THIRD被转成了小写, 而调用update和初始化函数时, 转小写并没有生效。必须要覆盖这两个方法才可以
In [6]: class LowerDict(dict):
...: def __init__(self, data):
...: data = {k.lower(): v for k, v in data.items()}
...: super().__init__(data)
...: def __setitem__(self, key, value):
...: key = key.lower()
...: super().__setitem__(key, value)
...: def update(self, data):
...: data = {k.lower(): v for k, v in data.items()}
...: super().update(data)
使用UserDict
使用UserDict作为父类来实现上述功能。
In [16]: class LowerDict(UserDict):
...: def __setitem__(self, key, value):
...: key = key.lower()
...: super().__setitem__(key, value)
...:
In [17]: data = LowerDict({"FIRST": 1, "SECOND": 2})
In [18]: data["THIRD"] = 3
In [19]: data.update({'FOURTH': 4})
In [20]: data
Out[20]: {'first': 1, 'second': 2, 'third': 3, 'fourth': 4}
结论:
当需要对内置数据类型进行拓展, 并且想要覆写其某些标准功能能时,应该使用
UserDict
,
UserList
, 和
UserString,而不是直接继承dict,list, str.
版权归原作者 be5yond 所有, 如有侵权,请联系我们删除。