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

泛映射类型

映射类型:不仅仅是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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA入门级教学之(super的内存示意)

Super的原理: 代表的是当前对象this的父类型特征 如果类加载过程中,这个类有静态代码块,有静态变量,一律都会执行,系统会先分配空间 只要方法调用,就一定会进行方法压栈 new一个方法,其实是调用…

python博客项目评论_Python 爬虫入门——小项目实战(自动私信博客园某篇博客下的评论人,随机发送一条笑话,完整代码在博文最后)...

之前写的都是针对爬虫过程中遇到问题的解决方案,没怎么涉及到实际案例。这次,就以博客园为主题,写一个自动私信博客下的评论人员(在本篇留下的评论的同学也会被自动私信,如果不想被私信,同时又有问题,请私信…

JAVA入门级教学之(猜数字测试)

一个类A有一个实例变量v,从键盘接受一个正整数作为实例变量v的初始值 另外再定义一个类B,对类A的实例变量v进行猜测 如果大了则提示大了 如果小了则提示小了 等于则提示测试成功 猜测数字比大小的测试: /*** author LBJ* version V1.0* P…

硬盘突然提示没有初始化_新硬盘的分区

★前言如果你添加了一个新硬盘到电脑上,但是它没有在文件管理器中出现,你可能需要为它分配一个盘符,或者对它进行初始化并分区才能使用。★警告在分区时,”删除磁盘分区“和”格式化“都会清空该分区的数据,请提前备份…

正高职称 程序员_正高级工程师评审条件最新版

.精选范本正高级工程师评审条件申报条件:学历资历条件具有大学本科以上学历,取得高级工程师资格后,从事本专业工作满5年。外语、计算机、继续教育条件(一)按照规定参加国家统一组织的职称外语和计算机应用能力考试,取得合格证&…

JAVA入门级教学之(简单的程序测试)

请定义一个交通工具(Vehicle)类 其中有属性: 速度speed 体积size 方法移动move() 设置速度setSpeed(int speed) 加速speedUp() 减速speedDown() 最后在测试类Vehicle中的main() 中实例化一个交通工具对象,并通过方法给它初始化speed&#xff0c…

linux怎样判断线程是否暂停_怎样判断股市是否会继续下跌?

之前和大家分享了如何判断大市是否会上涨,这篇文章我再分享下如何判断大市是否会继续下跌。我们对大市的判断原则仍采用:基于技术分析判断危险信号,结合市场消息坐实。基于上一篇文章的基础如何判断股市是否会上涨?是否已跌到底&a…

hfss螺旋平面_利用HFSS设计平面等角螺旋天线

- 73 -利用HFSS设计平面等角螺旋天线杜起飞北京理工大学电子工程系 100081摘要&#xff1a;本文介绍了一种双臂平面等角螺旋天线的设计过程&#xff0c;利用ANSOFT HFSS对其结构进行了建模和仿真&#xff0c;工作频率为0.4GHz&#xff5e;3GHz&#xff0c;电压驻波比VSWR<2.…

JAVA进阶教学之(源码及API文档概述)

1.JDK类库的根类&#xff1a;Object 这个从老祖宗类中的方法我们需要先研究一下&#xff0c;因为这些方法都是所有子类通用的。 任何一个类默认继承Object 就算没有直接继承&#xff0c;也会间接继承 2.Object类中有哪些常用的方法呢&#xff1f; 第一种&#xff1a;去源代码中…

达梦数据库删除用户_达梦数据库的操作手册.docx

达梦数据库操作手册2013年12月15日达梦数据库安装服务器安装数据库安装注意问题数据库的安装路径不要直接放在操作系统的/目录相同的磁盘上&#xff0c;可以安装在/dmdb/dm&#xff0c;但是/dmdb要单独挂载在一块硬盘上。根据业务需要及数据量&#xff0c;数据文件放在磁盘空间…

Java俄罗斯方块

游戏规则 由小方块组成的不同形状的板块陆续从屏幕上方落下来&#xff0c;玩家通过调整板块的位置和方向&#xff0c;使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失&#xff0c;给新落下来的板块腾出空间&#xff0c;与此同时&#xff0c;玩家得到分数奖励…

html鼠标悬停效果_【开发小技巧】023—如何使用HTML和CSS实现3D文字效果

来源 | https://www.geeksforgeeks.org/create-a-3d-text-effect-using-html-and-css/3D文字效果是网页设计领域中最常用的文字效果之一。作为设计师或前端开发人员&#xff0c;应该知道如何创建3D文字效果。今天&#xff0c;我们将研究一种最简单易用的方法来实现3D文字外观。…

JAVA进阶教学之(Object类的toString方法)

1.toString public String toString() 返回对象的字符串表示形式。总的来说&#xff0c;这 toString方法返回一个字符串&#xff0c;“以文本方式表示”这个对象。其结果应该是一个简洁&#xff0c;但详实的代表性&#xff0c;是一个容易阅读的人。 建议所有子类都重写此方法…

etcd nginx 容器_Etcd+Confd实现Nginx配置文件自动管理

一、需求我们使用Nginx做七层负载均衡&#xff0c;后端是Tomcat。项目采用灰度发布方式&#xff0c;每次项目升级&#xff0c;都要手动先从Nginx下摘掉一组&#xff0c;然后再升级这组&#xff0c;当项目快速迭代时&#xff0c;手动做这些操作显然会增加部署时间&#xff0c;于…

java ftp获取文件名的方法_小猿圈Java学习-URL地址的组成格式

URL的全称是Uniform Resource Locator&#xff0c;意思是统一资源定位符&#xff0c;俗称网络地址或网址。网络上的每个文件及接口&#xff0c;都有对应的URL网址&#xff0c;它规定了其他设备如何通过一系列的路径找到自己&#xff0c;犹如网购的包裹一路送至收货地址所描述的…

ceph编译_Ceph编译安装教程

Ceph官方版本目前支持的纠删码很有限&#xff0c;实验室这块希望能够整合我们自主开发的纠删码BRS(Binary Reed–Solomon encoding)&#xff0c;所以需要编译Ceph环境。Ceph官方目前推荐的安装方式都是通过Ceph-deploy的工具来安装配置&#xff0c;搭建起来十分简单。目前直接通…

JAVA进阶教学之(Object类中的equals方法)

public boolean equals(Object obj){return (this obj); } 原始equals方法是判断两个对象的内存地址是否相等的&#xff08;内存地址相等&#xff0c;保存的值也相等&#xff09; 比较是判断两个对象的值是否相等&#xff08;保存的值相等&#xff09; 在Object类中的equal…

hashmap扩容机制_图文并茂:HashMap经典详解!

点击上方 Java后端&#xff0c;选择 设为星标优质文章&#xff0c;及时送达代码中的注解多看几遍&#xff0c;其中HashMap的扩容机制是要必懂知识&#xff01;结合图片一起理解&#xff01;什么是 HashMap?HashMap 是基于哈希表的 Map 接口的非同步实现。此实现提供所有可选的…

python使用高阶函数实现_18.python高阶函数

什么是高阶函数&#xff1a;一个函数可以作为参数传给另外一个函数(一个函数可以用来接收另一个函数作为参数)&#xff0c;或者一个函数的返回值为另外一个函数(若返回值为该函数本身&#xff0c;则为递归)&#xff0c;满足其一则为高阶函数。函数的形参位置必须接受一个函数对…

JAVA进阶教学之(Object类中的hashCode方法)

import java.util.Objects;/* hashCode方法 在Object中的hashCode方法是怎样的&#xff1f; public native int hashCode(); 这个方法不是抽象方法&#xff0c;带有native关键字&#xff0c;底层调用的是c程序hashCode() 方法返回的是int类型的哈希码 实际上就是一个java对象的…