Python中的defaultdict模块和namedtuple模块的简单入门指南


Posted in Python onApril 01, 2015

在Python中有一些内置的数据类型,比如int, str, list, tuple, dict等。Python的collections模块在这些内置数据类型的基础上,提供了几个额外的数据类型:namedtuple, defaultdict, deque, Counter, OrderedDict等,其中defaultdict和namedtuple是两个很实用的扩展类型。defaultdict继承自dict,namedtuple继承自tuple。
一、defaultdict

 1. 简介

在使用Python原生的数据结构dict的时候,如果用d[key]这样的方式访问,当指定的key不存在时,是会抛出KeyError异常的。但是,如果使用defaultdict,只要你传入一个默认的工厂方法,那么请求一个不存在的key时, 便会调用这个工厂方法使用其结果来作为这个key的默认值。

defaultdict在使用的时候需要传一个工厂函数(function_factory),defaultdict(function_factory)会构建一个类似dict的对象,该对象具有默认值,默认值通过调用工厂函数生成。

2. 示例

下面给一个defaultdict的使用示例:
 

In [1]: from collections import defaultdict
 
In [2]: s = [('xiaoming', 99), ('wu', 69), ('zhangsan', 80), ('lisi', 96), ('wu', 100), ('yuan', 98), ('xiaoming', 89)]
 
In [3]: d = defaultdict(list)
 
In [4]: for k, v in s:
  ...:   d[k].append(v)
  ...:  
 
In [5]: d
Out[5]: defaultdict(<type 'list'>, {'lisi': [96], 'xiaoming': [99, 89], 'yuan': [98], 'zhangsan': [80], 'wu': [69, 100]})
 
In [6]: for k, v in d.items():
  ...:   print '%s: %s' % (k, v)
  ...:  
lisi: [96]
xiaoming: [99, 89]
yuan: [98]
zhangsan: [80]
wu: [69, 100]

对Python比较熟悉的同学可以发现defaultdict(list)的用法和dict.setdefault(key, [])比较类似,上述代码使用setdefault实现如下:
 

s = [('xiaoming', 99), ('wu', 69), ('zhangsan', 80), ('lisi', 96), ('wu', 100), ('yuan', 98), ('xiaoming', 89)]
d = {}
 
for k, v in s:
  d.setdefault(k, []).append(v)

3. 原理

从以上的例子中,我们可以基本了defaultdict的用法,下面我们可以通过help(defaultdict)了解一下defaultdict的原理。通过Python console打印出的help信息来看,我们可以发现defaultdict具有默认值主要是通过__missing__方法实现的,如果工厂函数不为None,则通过工厂方法返回默认值,具体如下:
 

def __missing__(self, key):
  # Called by __getitem__ for missing key
  if self.default_factory is None:
    raise KeyError((key,))
  self[key] = value = self.default_factory()
  return value

从上面的说明中,我们可以发现一下几个需要注意的地方:

a). __missing__方法是在调用__getitem__方法发现KEY不存在时才调用的,所以,defaultdict也只会在使用d[key]或者d.__getitem__(key)的时候才会生成默认值;如果使用d.get(key)是不会返回默认值的,会出现KeyError;

b). defaultdict主要是通过__missing__方法实现,所以,我们也可以通过实现该方法来生成自己的defaultdict,代码入下:

In [1]: class MyDefaultDict(dict):
  ...:   def __missing__(self, key):
  ...:     self[key] = 'default'
  ...:     return 'default'
  ...:  
 
In [2]: my_default_dict = MyDefaultDict()
 
In [3]: my_default_dict
Out[3]: {}
 
In [4]: print my_default_dict['test']
default
 
In [5]: my_default_dict
Out[5]: {'test': 'default'}

4. 版本

defaultdict是在Python 2.5之后才加入的功能,在旧版本的Python中是不支持这个功能的,不过,知道了它的原理,我们可以自己实现一个defaultdict。

# http://code.activestate.com/recipes/523034/
try:
  from collections import defaultdict
except:
  class defaultdict(dict):
 
    def __init__(self, default_factory=None, *a, **kw):
      if (default_factory is not None and
        not hasattr(default_factory, '__call__')):
        raise TypeError('first argument must be callable')
      dict.__init__(self, *a, **kw)
      self.default_factory = default_factory
 
    def __getitem__(self, key):
      try:
        return dict.__getitem__(self, key)
      except KeyError:
        return self.__missing__(key)
 
    def __missing__(self, key):
      if self.default_factory is None:
        raise KeyError(key)
      self[key] = value = self.default_factory()
      return value
 
    def __reduce__(self):
      if self.default_factory is None:
        args = tuple()
      else:
        args = self.default_factory,
      return type(self), args, None, None, self.items()
 
    def copy(self):
      return self.__copy__()
 
    def __copy__(self):
      return type(self)(self.default_factory, self)
 
    def __deepcopy__(self, memo):
      import copy
      return type(self)(self.default_factory, copy.deepcopy(self.items()))
 
    def __repr__(self):
      return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))

二、namedtuple

namedtuple主要用来产生可以使用名称来访问元素的数据对象,通常用来增强代码的可读性,在访问一些tuple类型的数据时尤其好用。其实,在大部分时候你应该使用namedtuple替代tuple,这样可以让你的代码更容易读懂,更加pythonic。举个例子:

from collections import namedtuple
 
# 变量名和namedtuple中的第一个参数一般保持一致,但也可以不一样
Student = namedtuple('Student', 'id name score')
# 或者 Student = namedtuple('Student', ['id', 'name', 'score'])
 
students = [(1, 'Wu', 90), (2, 'Xing', 89), (3, 'Yuan', 98), (4, 'Wang', 95)]
 
for s in students:
  stu = Student._make(s)
  print stu
 
# Output:
# Student(id=1, name='Wu', score=90)
# Student(id=2, name='Xing', score=89)
# Student(id=3, name='Yuan', score=98)
# Student(id=4, name='Wang', score=95)

在上面的例子中,Student就是一个namedtuple,它和tuple的使用方法一样,可以通过index直接取,而且是只读的。这种方式比tuple容易理解多了,可以很清楚的知道每个值代表的含义。

Python 相关文章推荐
使用Protocol Buffers的C语言拓展提速Python程序的示例
Apr 16 Python
利用Python获取赶集网招聘信息前篇
Apr 18 Python
Python实现向服务器请求压缩数据及解压缩数据的方法示例
Jun 09 Python
python九九乘法表的实例
Sep 26 Python
python pandas 组内排序、单组排序、标号的实例
Apr 12 Python
Python使用sort和class实现的多级排序功能示例
Aug 15 Python
Python 从一个文件中调用另一个文件的类方法
Jan 10 Python
python操作cfg配置文件方式
Dec 22 Python
python 输出列表元素实例(以空格/逗号为分隔符)
Dec 25 Python
Python3使用腾讯云文字识别(腾讯OCR)提取图片中的文字内容实例详解
Feb 18 Python
翻转数列python实现,求前n项和,并能输出整个数列的案例
May 03 Python
Python如何输出整数
Jun 07 Python
Python进行数据科学工作的简单入门教程
Apr 01 #Python
10个易被忽视但应掌握的Python基本用法
Apr 01 #Python
用Python制作检测Linux运行信息的工具的教程
Apr 01 #Python
用Python的pandas框架操作Excel文件中的数据教程
Mar 31 #Python
Python实现国外赌场热门游戏Craps(双骰子)
Mar 31 #Python
通过代码实例展示Python中列表生成式的用法
Mar 31 #Python
使用Python实现一个简单的项目监控
Mar 31 #Python
You might like
在phpstudy集成环境下的nginx服务器下配置url重写
2019/12/02 PHP
利用js实现选项卡的特别效果的实例
2013/03/03 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
2013/04/22 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
JS中自定义定时器让它在某一时刻执行
2014/09/02 Javascript
Labelauty?jQuery单选框/复选框美化插件分享
2015/09/26 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
Jquery修改image的src属性,图片不加载问题的解决方法
2016/05/17 Javascript
浅谈JSON.stringify()和JOSN.parse()方法的不同
2016/08/29 Javascript
javascript中apply/call和bind的使用
2017/02/15 Javascript
小程序实现多列选择器
2019/02/15 Javascript
利用es6 new.target来对模拟抽象类的方法
2019/05/10 Javascript
Python合并字典键值并去除重复元素的实例
2016/12/18 Python
python合并同类型excel表格的方法
2018/04/01 Python
python:print格式化输出到文件的实例
2018/05/14 Python
Pycharm 操作Django Model的简单运用方法
2018/05/23 Python
详解python3中的真值测试
2018/08/13 Python
Python运维自动化之nginx配置文件对比操作示例
2018/08/29 Python
Python基础之函数的定义与使用示例
2019/03/23 Python
pytorch下使用LSTM神经网络写诗实例
2020/01/14 Python
Python爬取YY评级分数并保存数据实现过程解析
2020/06/01 Python
python实现测试工具(一)——命令行发送get请求
2020/10/19 Python
HTML5事件方法全部汇总
2016/05/12 HTML / CSS
海外淘书首选:AbeBooks
2017/07/31 全球购物
彪马英国官网:PUMA英国
2019/02/11 全球购物
理工大学毕业生自荐信
2013/11/01 职场文书
数控机床专业自荐信
2014/05/19 职场文书
中秋节国旗下演讲稿
2014/09/13 职场文书
教师党的群众路线学习心得体会
2014/11/04 职场文书
委托公证书样本
2015/01/23 职场文书
2015年初中教师个人工作总结
2015/07/21 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
会议室管理制度范本
2015/08/06 职场文书
十一月早安语录:把心放轻,人生就是一朵自在的云
2019/11/04 职场文书
图神经网络GNN算法
2022/05/11 Python
SpringBoot使用ip2region获取地理位置信息的方法
2022/06/21 Java/Android