转载:https://mp.weixin.qq.com/s?timestamp=1498528588&src=3&ver=1&signature=DfFeOFPXy44ObCMO3yMBLLgt5iFzbFAuShvog4m*JYf1w-gLIDZd7VoPWJN5f36DbVcaBJi33DkfXw6i-h*F7t0-D5-AJsAX*NeUCQAvfR4AYY6g5HMEUFyKFH31O65ulsSDpRyQf4roj-ZQnOZhPBol9POO67N9YO4x29OvrzY=

  字典对象在Python中作为最常用的数据结构之一,和数字、字符串、列表、元组并列为5大基本数据结构,字典中的元素通过键来存取,而非像列表一样通过偏移存取。笔者总结了字典的一些常用Pyhonic用法,这是字典的Pythonic用法的上篇

1、 使用 in/not in 检查 key 是否存在于字典

  判断某个 key 是否存在于字典中时,一般初学者想到的方法是,先以列表的形式把字典所有键返回,再判断该key是否存在于键列表中:

dictionary = {}

keys = dictionary.keys()

for k in keys:

if key == k:

print True

break

  更具Pythonic的用法是使用in关键字来判断 key 是否 存在于字典中:

if key in dictionary:

print True

else:

print False

  2、使用 setdefault() 初始化字典键值

  使用字典的时候经常会遇到这样一种应用场景:动态更新字典,像如下代码,如果 key 不在 dictionary 中那么就添加它并把它对应的值初始为空列表 [] ,然后把元素 append 到空列表中:

dictionary = {}

if "key" not in dictionary:

dictionary["key"] = []

dictionary["key"].append("list_item")

  尽管这段代码没有任何逻辑错误,但是我们可以使用setdefault来实现更Pyhonic的写法:

dictionary = {}

dictionary.setdefault("key", []).append("list_item")

  字典调用 setdefault 方法时,首先检查 key 是否存在,如果存在该方法什么也不做,如果不存在 setdefault 就会创建该 key,并把第二个参数[]作为 key 对应的值。

  3、 使用 defaultdict() 初始化字典

  初始化一个字典时,如果初始情况下希望所有 key 对应的值都是某个默认的初始值,比如有一批用户的信用积分都初始为100,现在想给 a 用户增加10分

d = {}

if 'a' not in d:

d['a'] = 100

d['a'] += 10

  同样这段代码也没任何问题,换成更pyhtonic的写法是:

from collections import defaultdict

d = defaultdict(lambda: 100)

d['a'] += 10

  defaultdict 是位于 collections 模块下,它是 dict 类的子类,语法结构是:

class collections.defaultdict([default_factory[, ...]])

  第一个参数default_factory是一个工厂方法,每次初始化某个键的时候将会被调用,value就是default_factory返回的值,剩下的参数和dict()函数接收的参数一样

  4、使用 iteritems() 迭代大数据

  迭代大数据字典时,如果是使用 items() 方法,那么在迭代之前,迭代器迭代前需要把数据完整地加载到内存,这种方式不仅处理非常慢而且浪费内存,下面代码约占1.6G内存(为什么是1.6G?可以参考:

  http://stackoverflow.com/questions/4279358/pythons-underlying-hash-data-structure-for-dictionaries)

d = {i: i * 2 for i in xrange(10000000)}

for key, value in d.items():

print("{0} = {1}".format(key, value))

  而使用 iteritem() 方法替换 items() ,最终实现的效果一样,但是消耗的内存降低50%,为什么差距那么大呢?因为 items() 返回的是一个 list,list 在迭代的时候会预先把所有的元素加载到内存,而 iteritem() 返回的一个迭代器(iterators),迭代器在迭代的时候,迭代元素逐个的生成。

d = {i: i * 2 for i in xrange(10000000)}

for key, value in d.iteritem():

print("{0} = {1}".format(key, value))

  5、高效合并字典

  普通方法

  合并多个字典的时候可以用一行代码实现:

x = {'a': 1, 'b': 2}

y = {'b': 3, 'c': 4}

z = dict(x.items() + y.items())

  这种写法看起来很Pythonic,但仔细分析的话,它的执行效率并不高,items()方法在python2.7中返回的是列表对象,两个列表相加得到一个新的列表,这样内存中存在3个列表对象,如果两个列表的大小都是1G,那么执行这段代码需要占用4G的空间来创建这个字典。此外这段代码在Python3中会报错,因为python3中items()返回的是dict_items对象,而不是列表。

>>> c = dict(a.items() + b.items())

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

  在python3中,你需要明确地强制转换成list对象:

z = dict(list(x.items()) + list(y.items()))

  Pythonic方法

  在Python3.5中提供了一种全新的Pythonic方法:

z = {**x, **y}

  不过考虑到大部分系统还是基于Python2,所以一种更兼容的pythonic方法是:

z = x.copy()

z.update(y)

  当然,你可以把它封装成一个函数:

def merge_dicts(*dict_args):

'''

可以接收1个或多个字典参数

'''

result = {}

for dictionary in dict_args:

result.update(dictionary)

return result

z = merge_dicts(a, b, c, d, e, f, g)

  其他方法

  还有其他方式来合并字典,但是性能不一定是最优的,比如: python2.7可以支持字典推导式

{k: v for d in dicts for k, v in d.items()}

  python2.6及以下版本使用

{k: v for d in dicts for k, v in d.items()}

  性能对比

import timeit

>>> min(timeit.repeat(lambda: {**x, **y}))  # python3.5

0.4094954460160807

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))

0.5726828575134277

>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))

1.163769006729126

>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))

2.2345519065856934

  直接使用python3.5中的{**x, **y}是最快的,使用update次之,用字典推导式相对来说是最慢的。

字典对象的 Pythonic 用法(上篇:转载)的更多相关文章

  1. 字典对象的 Pythonic 用法(上篇)

    字典对象在Python中作为最常用的数据结构之一,和数字.字符串.列表.元组并列为5大基本数据结构,字典中的元素通过键来存取,而非像列表一样通过偏移存取.笔者总结了字典的一些常用Pyhonic用法,这 ...

  2. Python成长之路第二篇(3)_字典的置函数用法

    字典的置函数用法(字典dict字典中的key不可以重复) class dict(object): """ dict() -> new empty dictionar ...

  3. Objective-c 字典对象

    oc 中的 NSDictionary 的作用同 java 中的字典类相同,提供了 “键-值”对的组合.比如,是用字典类实现对学生姓名和学号的存放,编号是一个键(唯一性),姓名是值.它的方法有: 下面通 ...

  4. 深入理解JavaScript系列(47):对象创建模式(上篇)

    介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...

  5. Python中super的用法【转载】

    Python中super的用法[转载] 转载dxk_093812 最后发布于2019-02-17 20:12:18 阅读数 1143  收藏 展开 转载自 Python面向对象中super用法与MRO ...

  6. VBS使用Scripting.Dictionary字典对象

    Scripting.Dictionary是个很有用的组件,其创建了类似于Key索引对应Value值的字典对象,并且在其内部提供了快速索引访问的机制,可以让我们通过Key直接索引到指定的Value,比遍 ...

  7. python 基础学习(字典对象,set对象)

    1.dict 字典对象 a.定义对象 d={'a':14,'b':12}b.通过key获取value d['a'] 方法1.判断key是否存在 if 'a' in d: d['a']方法2:通过用ge ...

  8. JavaScript中创建字典对象(dictionary)实例

    这篇文章主要介绍了JavaScript中创建字典对象(dictionary)实例,本文直接给出了实现的源码,并给出了使用示例,需要的朋友可以参考下 对于JavaScript来说,其自身的Array对象 ...

  9. DOM Style样式对象的详细用法

    DOM Style样式对象的详细用法 HTML Style样式比较复杂,相应访问.修改方法也有所差异.参考相关资料,整理如下. 典型Html文件如下,有三种定义方式. <head>     ...

随机推荐

  1. gpio子系统和pinctrl子系统(上)

    前言 随着内核的发展,linux驱动框架在不断的变化.很早很早以前,出现了gpio子系统,后来又出现了pinctrl子系统.在网上很难看到一篇讲解这类子系统的文章.就拿gpio操作来说吧,很多时候都是 ...

  2. 搭建git for windows服务器(100%可以成功)【转】

    转自:http://blog.csdn.net/code_style/article/details/38764203 既然Git在linux下面非常好用,为什么还要搭建git windows的服务器 ...

  3. sql文格式替换

    SELECT COUNT(1)FROM TAB1 TWHERE T.IS_DEL <> 0 将以上SQL格式替换为代码中的格式 sql.AppendLine(" SELECT & ...

  4. cobbler部署安装

    挂载光驱 # mount /dev/cdrom /mnt/ 安装cobbler所需软件 # yum install cobbler cobbler-web dhcp tftp-server pykic ...

  5. hdu 1068(最大独立集)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. MySQL阅读笔记

    左连接:包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录.右连接:包含所有的右边表中的记录甚至是左边表中没有和它匹配的记录. select ename,deptname from emp le ...

  7. django static文件的引入方式(转)

    1. 在django project中创建 static文件夹 2.settings.py中配置要在 STATIC_URL = '/static/'  下边 STATICFILES_DIRS = [ ...

  8. 洛谷——P1604 B进制星球

    P1604 B进制星球 题目背景 进制题目,而且还是个计算器~~ 题目描述 话说有一天,小Z乘坐宇宙飞船,飞到一个美丽的星球.因为历史的原因,科技在这个美丽的星球上并不很发达,星球上人们普遍采用B(2 ...

  9. 1090: MTM (费用流)

    1090: MTM Time Limit:3000/1000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total S ...

  10. web前端读取文本文件内容

    html5+js实现,参照xxyy888的CSDN博客文章<使用HTML+javascrpt读取txt文本文件>失败,将作者文章中的代码重新整理了下依然不行,文章代码存在的问题是括号错误, ...