python核心数据结构之字典

时间:2021-12-02 21:12:21

![](http://images2015.cnblogs.com/blog/1182370/201706/1182370-20170628210759774-266944364.jpg)

[TOC]

字典是Python核心数据类型中唯一的一种映射类型, 通过键而不是相对位置来存取数据, 具有可变性.除了列表之外, 字典或许是Python最灵活的内置数据结构:-D

### 映射操作

1\. 作为常量编写, 字典编写与大括号`{}`中, 包含一系列的`键:值`对,并通过逗号`,`将不同的`键:值`对分开, 类型名 `dict`, 可以通过dir(dict)查看函数,或者help(dict)查询详细信息

2\. 字典常用于将一系列`键` 与`值`相关联,例如描述物品的属性,

D = {'trademark': 'iphone', 'Release':'6s', 'screen': 5}

3\. 可以通过键来读取或者改变键对应的值, 对一个新的字典的键赋值会创建该键

```py
>>> D['trademark']
'iphone'
>>> D['screen'] = 4.7
>>> D
{'trademark': 'iphone', 'screen': 4.7, 'Release': '6s'}
>>> D['price'] = 6000
>>> D
{'trademark': 'iphone', 'screen': 4.7, 'Release': '6s', 'price': 6000}
>>>

```

### 嵌套
通过下面的代码可以清晰的知道python字典的嵌套特点,从中可以看到其结构类型很灵活, 使用起来很方便

```python
>>> person =
{'name':{'first':'now', 'last':'good'},
'skill': ['java', 'python'],
'age': 24}
>>> person
{'skill': ['java', 'python'], 'age': 24, 'name': {'first': 'now', 'last': 'good'}}
>>> person['name']
{'first': 'now', 'last': 'good'}
>>> person['name']['last']
'good'
>>> person['skill'][-1]
'python'
>>> person['skill'].append('shell')
>>> person
{'skill': ['java', 'python', 'shell'], 'age': 24, 'name': {'first': 'now', 'last': 'good'}}

```

### 键的排序

字典不是序列,它不包含任何可靠的从左到右的顺序,这意味着如果我们没法通过索引获取字典元素;

那么在字典的元素中,我们确实需要强调某种顺序的时候应该怎么做?

* 通过keys()方法获取一个键的列表
* 通过列表的sort()方法进行排序

```py
>>> D = {'a':1, 'b':2, 'c':3}
>>> D
{'c': 3, 'b': 2, 'a': 1}
>>> D.keys()
dict_keys(['c', 'b', 'a'])
>>> type(D.keys())

>>> keys = list(D.keys())
>>> keys
['c', 'b', 'a']
>>> keys.sort()
>>> keys
['a', 'b', 'c']
>>>
```

---
注意上面的`list`的sort()方法会直接操作key本身,返回为None

L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*

上述操作可以使用 `sorted`内置函数一步完成

```py
>>> sorted(D)
['a', 'b', 'c']
>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, key=None, reverse=False)
Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customise the sort order, and the
reverse flag can be set to request the result in descending order.

>>>
```
### 不存在的键: if 测试

尽管可以通过给新的键赋值来扩展字典, 但是获取一个不存在的键的值依然是一个错误

我们编写程序的时候并不是总是知道当前数据存在那些键, 为了避免错误发生, 一个技巧就是首先进行测试, `in`关系表达式允许我们查询字典中的一个键是不是存在

```py
>>> D = {'a':1, 'b':2, 'c':3}
>>> D
{'c': 3, 'b': 2, 'a': 1}
>>> 'f' in D
False
>>> 'b' in D
True
>>>
```

### 字典的主要属性
通过上述操作,来总结下字典的属性

1. 通过键而不是偏移量来存取数据
2. 任意对象的无序集合
3. 可变长, 异构, 任意嵌套
4. 属于可变映射类型
5. 字典存储的是对象引用(而不是拷贝)

字典使用注意事项:

* 键不一定总是字符串, 任何不可变对象都是可以的
* 避免missing-key错误,使用 in 关系表达式测试

### 常见字典常量和操作

操作 | 说明
--- | ---
D = {} | 空字典
D = dict.from(['a','b']) | 构造字典, 注意中括号[ ]
D = dict(zip(keyslist, vallist)) | 对应的键值列表
D = dict(name='NowGood', age=42) | 构造字典
D['size'] | 获取对应键的值
'b' in D | 成员关系运算:键存在测试
D.keys() | 获取键字典视图
D.values() | 获取值字典视图
D.items() | 返回(key, values)字典视图
D.copy() | 拷贝, 避免字典共享引用潜在的副作用
D.get(k[,d]) | D[k] if k in D, else d.d defaults to None.
D.update(D2) | 将D2合并到D, 如果有相同的键, 合并后的值来自D2中
D.pop(key) | 删除等
len(D) | 存储元素的个数
del D[key] | 根据键删除条目
list(D.keys()) | 字典视图(python3)
D1.keys() & D2.keys() | 返回D1与D2 键的交集
D = {x: x*2 for x in range(10)} | 字典解析

> 对于D.key(), D.values(), D.items()方法,返回可迭代的视图, 而不是列表

```python
>>> d = dict.fromkeys('a', 'b')
>>> d
{'a': 'b'}
>>> d = dict.fromkeys(['a', 'b'])
>>> d
{'b': None, 'a': None}
>>> d.keys()
dict_keys(['b', 'a'])
>>> d.items()
dict_items([('b', None), ('a', None)])
>>> D = {'a':1, 'b':2, 'c':3}
>>> D.keys()
dict_keys(['c', 'b', 'a'])
>>> D.values()
dict_values([3, 2, 1])
>>> D.items()
dict_items([('c', 3), ('b', 2), ('a', 1)])
>>> D.get('c')
3
>>> D.get('d')
>>> d = D.copy()
>>> d
{'c': 3, 'b': 2, 'a': 1}
>>> D.update({'e':1})
>>> D
{'c': 3, 'e': 1, 'b': 2, 'a': 1}
>>> D.update({'c':1})
>>> D
{'c': 1, 'e': 1, 'b': 2, 'a': 1}
>>> d.keys() & D.keys()
{'c', 'b', 'a'}
>>> D = {x: x*2 for x in range(10)}
>>> D
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}
>>> d
{'c': 3, 'u': 1, 'b': 2, 'a': 10}
>>> d.pop('c')
3
>>> d
{'u': 1, 'b': 2, 'a': 10}
>>> >>>
```

### 创建字典的方法

#### 1. 常见的方法

1\. {'name': 'me', 'age':24}

2\.
D = {}
D['name'] = 'me'
D['age'] = 24

3\. dict(name='mel', age=45)

4\. dict([('name', 'me'), ('age',45)])

这4种方式在不同条件下有用:

* 如果实现可以拼出来整个字典, 那么第一种很方便
* 如果需要一次动态的建立字典的一个字段, 第二种比较合适
* 第三种关键字形式所需的代码一般比常量少, 但是键必须都是字符串才行
* 如果你需要在程序运行时把键和值逐步建立序列, 最后一种比较有用,这种形式通常和zip函数一起使用, 把程序运行时动态获取得键和值不同的列表合并在一起

如果所有的值都相同,你也可以通过特殊的形式对字典初始化,简单的传入一个键列表, 所有的键的初始值(默认为空)

```py
>>> dict.fromkeys(['a', 'b'], 1)
{'b': 1, 'a': 1}
>>>
```

#### 2. 通过字典解析创建字典

字典解析只在 python3.0中可用

动态的初始化一个字典的标准形式: 将其键和值对应起来并把结果传递个dict调用.

zip函数是在单个调用中从键和值得列表构建一个字典的方式之一.如果不能预计键和值的集合, 总是可以将他们构建为列然后对应起来

```py
>>> list(zip(['a','b','c'], [1,2,3]))
[('a', 1), ('b', 2), ('c', 3)]
>>> D = dict(zip(['a','b','c'], [1,2,3]))
>>> D
{'c': 3, 'b': 2, 'a': 1}
```

##### 字典解析

```py
>>> D = {k:v for (k, v) in zip(['a','b','c'], [1,2,3])}

>>> D
{'c': 3, 'b': 2, 'a': 1}
>>> D = {x: x*2 for x in range(10)}
>>> D
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}

>>> D = {w: w*3 for w in 'apple'}
>>> D
{'e': 'eee', 'l': 'lll', 'p': 'ppp', 'a': 'aaa'}
>>>
```

通过键来初始化字典:

```py
>>> dict.fromkeys(['a', 'b'], 1)
{'b': 1, 'a': 1}
>>> {k:1 for k in ['a', 'b']}
{'b': 1, 'a': 1}
>>> dict.fromkeys('apple')
{'e': None, 'l': None, 'p': None, 'a': None}
>>>
```

### 字典视图

python3.0中, 字典的keys(), values(), items()都是返回视图类型

* 视图类型是可迭代的,这意味着对象每次产生一个结果, 而不是在内存中立即产生结果列表;
* 字典视图还保持字典成分的最初顺序, 反映字典未来的修改;
* 支持集合操作, 如并集,交集操作;
* 字典视图不是列表, 并不支持像索引和列表sort()方法这样的操作, 打印的时候也不显示自己的项

如果想要应用列表操作或者显示他们的值, 我们必须通过内置list()函数,来讲这三个方法的结果转成list

D = dict(a=1, b=2, c=3)

```py
>>> D = dict(a=1, b=2, c=3)
>>> D
{'c': 3, 'b': 2, 'a': 1}
>>> D.keys()
dict_keys(['c', 'b', 'a'])
>>> list(D.keys())
['c', 'b', 'a']
>>> D.values()
dict_values([3, 2, 1])
>>> list(D.values())
[3, 2, 1]
>>> D.items()
dict_items([('c', 3), ('b', 2), ('a', 1)])
>>> list(D.items())
[('c', 3), ('b', 2), ('a', 1)]
>>> D.items()[0]
Traceback (most recent call last):
File "", line 1, in
D.items()[0]
TypeError: 'dict_items' object does not support indexing
>>>
```

Python3.0 的字典自己拥有迭代器, 它返回连续键, 往往没有必要直接调用keys()

```py
>>> for k in D:
print(k)
c
b
a
```