泛映射类型

映射类型:不仅仅是dict,标准库里的所有映射类型都是利用dict来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用做这些映射的键。(只有键有这个需求,值并不需要必须是可散列的数据类型。)

什么是可散列的数据类型?

可散列的对象在它的生命周期中,散列值是不变的,需要实现__hash__()方法。另外散列对象还要有__eq__()方法,这样才能跟其他键作比较。 - 原子不可变数据类型都是可散列的(str,bytes和数值类型,frozenset) - dict,list是不可散列的

用setdefault处理找不到的键

当字典d[k]找不到值会抛出异常,通常我们使用d.get(k,default)来代替d[k],给找不到的键默认一个返回值。 但是要更新某个键对应的值的时候,不管是用__getitem__还是get都不太自然的,效率很低。

# 这样使用 setdefaultmy_dict.setdefault(key,[]).append(new_value)# 跟这样写使用默认的dictif key not in my_dict:

my_dict[key]=[]my_dict[key].append(new_value)

两者的效果是一样的,只不过后者至少要进行两次查询——如果键不存在的话,就是三次,使用setdefault只需要一次就可以完成整个操作。

映射的弹性查询

所谓的弹性查询就是,我找的键不在映射里面存在的时候,也能返回一个默认值比如

d.get(key,default)

python有两个途径达到整个目的, - 一个是通过defaultdict这个类型而不是普通的dict - 另一个是给自己顶一个dict的子类,然后在子类中实现__missing__方法。

defaultdict:处理找不到的键的一个选择

dd = defaultdict(list) print(dd['new-key']) # []"""调用list()来建立一个列表。把这个新列表作为值,'new-key'作为它的键,放到dd中。返回这个列表的引用。"""print(dd) #defaultdict(, {'dddd': []})

注意如果在创建defaultdict的时候没有指定default_factory,查询不存在键会触发KeyError

特殊方法__missing__

所有的映射类型找不到键的时候,都会使用到__missing__方法。 虽然基类dict并没有定义这个方法,但是dict知道有这么个东西的存在。 也就是说,如果有一个类继承了dict,然后这个继承类提供了__missing__方法, 那么在__getitem__碰到找不到键的时候,python会自动调用它,而不是抛出一个KeyError异常。 __missing__方法只会被__getitem__调用

字典的变种

collections.OrderedDict:这个类型在添加键的时候会保持顺序,因此键的迭代次序总是一致的。

collections.ChainMap:该类型可以容纳数个不同的对象,然后在进行键查找操作的时候,这些对象会被当做一个整体逐个被查找。

import collections# 初始化字典dict1 = {'a': 1, 'b': 2}dict2 = {'b': 3, 'c': 4}# 初始化ChainMapchain = collections.ChainMap(dict1, dict2)# 使用maps输出chainMapprint(chain.maps)  # [{'b': 2, 'a': 1}, {'b': 3, 'c': 4}]# 输出keyprint(list(chain.keys()))  # ['b', 'c', 'a']# 输出值print(list(chain.values()))  # [2, 4, 1]# 访问print(chain['b'])  # 2print(chain.get('b'))  # 2# 使用new_child添加新字典dict3 = {'f': 5}new_chain = chain.new_child(dict3)print(new_chain.maps)  # [{'f': 5}, {'b': 2, 'a': 1}, {'b': 3, 'c': 4}]reversed(new_chain.maps)print(new_chain.maps)

collections.Counter:这个映射类型会给键准备一个整数计数器。每次更新一个键的时候都会增加这个计数器。

collections.UserDict:把标准的dict用纯python又实现了一遍。

不可变的映射类型

标准库里所有的映射类型都是可变的,如果遇到不能让用户错误的修改某个映射。 使用types.MappingProxyType,如果给这个类一个映射,它会返回一个只读的映射视图(动态的)。

集合

相对dict,set这个概念在python算是比较年轻的,有set 跟 frozenset 集合的本质是许多唯一对象的聚集,所以集合中的元素必须都是可散列的,set类型本身是不可散列的,但是frozenset时可散列的。 集合可以进行中缀运算符。

dict和set的背后python里的dict和set的效率有多高?

为什么它们是无序的?

为什么并不是所有的python对象都可以当做dict的键或者是set的元素?

为什么dict的键和set元素的顺序是根据他们被添加的次序而定的,以及为什么在映射对象的生命周期中,这个顺序是一成不变的?

为什么不应该在迭代循环dict或者是set的同时往里添加元素?

字典中的散列表

散列表其实是一个稀疏数组(总是有空白元素的数组成为稀疏数组) 散列表里的单元通常叫做表元(bucket),在dict的散列表中每个键值对都占用一个表元,每个表元分都有两个部分,一个是对键的引用,一个是对值的引用。 如果把对象放到散列表,那么首先要计算这个元素键的散列值,python中可以用hash()方法来做这个事情。

散列值和相等性

如果1==1.0为真,那么`hash(1)==hash(1.0)也必须为真

散列表算法

为了获取my_dict[search_key]背后的值,Python首先调用hash(search_key)来计算search_key的散列值,把这个值最低的几位数字当做偏移量,在散列表里查找表元(具体取几位,得看当前散列表的大小)。 若找到的表元为空的,则抛出KeyError异常。若不为空的,则表元里会有一对found_key:found_value。 这时候python会检验search_key == found_key是否为真,如果它们相等,就回返回found_value。 如果search_key和found_key不匹配的话,这种情况称为散列冲突。 发生原因是散列表所做的其实是把随机的元素映射到只有几位的数字上,而散列表本身的索引又只依赖于这个数字的一部分。 为了解决散列冲突,算法会在散列值中另外再取几位,然后用特殊方法处理一下,把新的到的数据在当做索引来寻找表元。

问题:如果定位一个表元?[^2]

dict的实现及其导致的结果

散列表带给dict的优势和限制。

键必须是可散列的

一个可散列的对象必须满足以下的需求: - 支持hash()函数,并且通过__hash__()方法所得到的散列值是不变的。 - 支持通过__eq__()方法来检测相等性。 - 若 a == b为真,则hash(a) == hash(b)也为真。

用户自定义的对象默认是可散列的,它们的散列值有id()来获取。

字典在内存上面开销巨大

通常不需要优化,如果数据量巨大考虑使用tuple()来替代dict()

特殊方法__slots__

键查询很快

dict的实现是典型的空间换时间

键的次序取决于添加顺序

当往dict中添加新建而又发生散列冲突的时候,新建可能会被安排存放在另个一个位置。

dict([key1,value1],[key2,value2]) == dict([key2,value2],[key1,value1]) # true

虽然键的次序是乱的,但是被视作相等的。这就是为什么说字典是无序的原因。

往字典中添加新建可能会改变已有键的顺序

无论何时往字典添加新的键,Python的解释器都可能做出为字典扩容的决定。 扩容导致的结果是需要一个更大散列表,并把字典里已有的元素添加到新表里,这个过程就可能出现散列冲突,导致新的散列表中的键的次序变化。

所以不要对字典同时迭代和修改。 python3中的.keys() .items() 和.values()方法返回都是字典的视图,这些方法返回的值更像是集合。

set的实现以及导致的结果可以参照没有值dict

python字典和集合对象可以进行索引操作_Python中的字典跟集合整理笔记相关推荐

  1. python字典和集合对象可以进行索引操作_python字典和列表的高级应用

    1.将序列分解为单独的变量 1.1问题 包含n个元素的元组或列表.字符串.文件.迭代器.生成器,将它分解为n个变量 1.2方案 直接通过赋值操作 要求:变量个数要等于元素个数 当执行分解操作时,有时需 ...

  2. python字典和集合对象可以进行索引操作_建议收藏丨纯知识点:Python基础—字典、集合操作大全...

    本文为纯知识点,预计需阅读二十分钟 数据结构基本上就是--它们是可以处理一些 数据 的 结构 .或者说,它们是用来存储一组相关数据的. 在Python中有四种内建的数据结构--列表.元组和字典,集合. ...

  3. python字典和集合对象可以进行索引操作吗_python 集合(set)和字典(dictionary)的用法解析...

    Table of Contents generated with DocToc ditctaionary and set hash 介绍 hash是计算机中非常常见一种查找的手法,它可以支持常数时间的 ...

  4. Python 数据分析三剑客之 Pandas(二):Index 索引对象以及各种索引操作

    CSDN 课程推荐:<迈向数据科学家:带你玩转Python数据分析>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python ...

  5. [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具

    原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.G ...

  6. Dataset:数据集集合(综合性)——机器学习、深度学习算法中常用数据集大集合(建议收藏,持续更新)

    Dataset:数据集集合(综合性)--机器学习.深度学习算法中常用数据集大集合(建议收藏,持续更新) 目录 常规数据集 各大方向分类数据集汇总 具体数据集分类 相关文章 DL:关于深度学习常用数据集 ...

  7. python字典和集合对象可以进行索引_Python字典和集合

    1.泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象类,他们的作用是为dict和其他类似的类型定义形式接口. 标准库里所有映射类型都是 ...

  8. python字典和集合对象可以进行索引_python集合和字典

    Python也包含有 集合 类型.集合是由不重复元素组成的无序的集.它的基本用法包括成员检测和消除重复元素.python集合对象也支持像 联合,交集,差集,对称差分等数学运算. 花括号或 set() ...

  9. python集合和字典的区别_Python中的字典和集合

    导语:本文章记录了本人在学习Python基础之数据结构篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流. 本文重点: 1.掌握常见的字典创建,查询,判别方法: 2.了解字典中的 ...

最新文章

  1. linux 非交互ssh sshpass简介
  2. APK加壳【2】内存加载dex实现详解
  3. mfcc中的fft操作_简化音频数据:FFT,STFT和MFCC
  4. VM异常关闭后导致虚拟机无法打开问题解决办法【已解决】
  5. Fiddler 详尽教程与抓取移动端数据包
  6. 阐述HTML语言的基本语法规则,HTML基本语法和语义写法规则与实例
  7. python3,进程间的通信
  8. Java 一维数组 二维数组 三维数组
  9. Console-算法[for]-素数
  10. 创建属于自己的OneNote插件
  11. 浅谈shadow dom
  12. 逆火软件测试工资,HyperXPulsefireFPS逆火评测 值不值得买
  13. 执行throw后 后面代码还会执行吗?
  14. 美国最常见英文名字排行榜(500名)
  15. 玲珑学院OJ 1130 - 喵哈哈村的魔法大师╳灬兲笙疯癫°月【强连通+可相交最小路径覆盖+背包】
  16. 用于理解C++类中静态成员的单子模式研究
  17. python:sxtwl(日历库)
  18. 喜马拉雅转道港交所:上半年亏损3个亿,负债200亿元,现金流紧张
  19. ElasticSearch教程
  20. 【Github】使用github

热门文章

  1. WebSocket教程(一)
  2. string.Format格式化输出
  3. Android开发中依赖注入的应用
  4. webservice 原理
  5. jquery filter和not
  6. 数据结构与算法——二分查找与二叉排序树
  7. 项目:基于以太网通信,单片机作为客户端,接收CAN-Ethernet的十六进制数据
  8. linux基础知识——CPU相关知识
  9. 3.6数对 (Python)
  10. 《动手学深度学习 PyTorch版》学习笔记(二):自动求梯度