编程学习
🐍Python(2)- 字典概述
00 分钟
2023-4-15
2023-11-23
type
status
date
slug
summary
tags
category
icon
password
Email

字典

创建字典的方式

字典由 关键字 组成。
由于关键字需要是索引,因此关键字必须是 不可变类型。通常为字符串或者数值,不能用列表做关键字。
字典的创建形式: {关键字: 值} 中间使用:分割

字典的关键字可以组成列表:
list 形成列表, sorted 对列表排序

使用 dict 直接创建字典:
dict中形成字典的大括号既可以使用 {} 也可以使用 [] ,但是键值对必须()

使用字典推导式创建字典:以任意键值对作为元素的可迭代对象中构建出字典。

dict 创建关键字都是字符串类型的字典:
字面语法与构造方法:

setdefault

一个统计文本中所有单词出现的行列坐标的程序:

defaultdict

提供了一个为找不到的键创建默认值的方法:
如果index没有word的值,则会调用 default_factory 为查询不到的键创建一个值,这个值在这里是一个 空列表 ,然后赋值给 words_dict[word],并且是一个引用,然后可以执行 append的操作。
如果在创建 defaultdict 的时候没有指定 default_factory,查询不存在的键会触发 KeyError

__missing__方法

当对象找不到某个键的时候,可以通过这个方法自定义会发生什么。
对于我们实现自定义的字典,并且重写特定方法时,这个方法很有用。
尤其是用于 UserDict 中(下文讲解)

字典的变种

collections.OrderedDict 添加键的时候会保持顺序,保持迭代顺序也始终是一致的。
它具有 popitem 方法,其默认删除最后一个元素,如果设置 last=False,则删除的就是第一个元素,并且返回这个值

collections.ChainMap 可以把多个映射集合到一个视图里面
在进行键查找操作的时候,这些对象会被当作一个整体被逐个查找,直到键被找到为止

collections.Counter 可以产生一个具有计数功能的映射,
使用 update 可以进行更新

collections.UserDict 把Dict用纯python纯写的,UserDict非常适合于继承。
可以说它封装了字典对象,简化了字典子类化
它具有一个 data 属性,其中存储着 Dict真正的数据,这才是一个真正的字典。

子类化UserDict

如果要创建自定义类型,则使用 UserDict 比使用普通的dict要方便的多。
创建一个可以自动将非字符串类型的键 转换为字符串类型并且进行查询,修改,删除的字典:
字典的构造过程:
  1. 首先通过构造函数进入 __init__ 函数进行对象的构造,然后如果传入的dict不是空,则会进入 update 函数进行插入键值对.
  1. 进入到 update 函数后,首先检查传入的参数是否是 Mapping 映射类型,如果是则进行下一步。
  1. 然后 键值对 的插入操作,进入到 __setitem__ 函数中,我们重写这个函数,把键全部改为str类型,因此我们无论输入的键是什么类型,都会是str类型
字典的 in 操作:
  1. in 操作会执行 __contains__ 函数,因此在此函数中我们直接把key值变为str类型,然后使用内置的 in 进行查询
字典的查询操作:
  1. 通过 sdict[i] 查询一个值,首先会进入 __getitem__ 函数中,如果查询的键不存在,则会进入到一个 __missing__ 函数中,该函数用来进行查询不到键时该如何操作
  1. 在此函数中,我们判断如果这个不存在的键是str类型,则意味着这个键是合法的,但是却没有值,因此它确实没有这个值,抛出 KeyError 异常。
  1. 如果我们的键是int类型,但是str(int)的键却是有值的,因此将key 转换为 str(key) 然后再次进入到 __getitem__ 中查询类型为str的键是否存在值,如果没有,则执行 2操作,抛出异常,然后退出。如果有值,则返回。

不可变映射类型

字典都是可变的,有没有一种字典是不可变的呢?
types 模块的 MappingProxyType 提供了这样一种方法。
在MappingProxyType对象中执行更改操作会出错,因为它返回的只是一个只读视图
但是在源对象中更改是允许的。对原映射做出了改动,我们通过这个视图可以观察到。

字典的实现

dict内部使用散列表实现
使用散列表会给字典带来哪些优势和限制呢?
  • 字典的键必须是可散列的。
  • 字典在内存上开销巨大
  • 键查询很快
  • 键的次序取决于添加次序
  • 往字典里添加新键可能会改变已有键的顺序

什么是可散列的?一个可散列的对象必须满足以下的条件:
  1. 必须支持 hash() 函数,并且通过 hash() 函数得到的散列值是不可变的。
  1. 支持通过 __ eq__来检测相等性
  1. 如果 a==b ,则 hash(a)==hash(b) 必须成立
  1. 所有用户自定义的对象都是可散列的,因为他们的散列值是通过id来获得的,并且他们都是不相等的。
 
 
 
 
 

评论
  • Twikoo
  • Valine