前言
字典是一种key-value结构,
redis、mencached、json都是这种结构
定义
>>> d = {}
>>> type(d)
<class 'dict'>
>>> d
{}
这里需要值得注意的是:
集合的定义里面是:s = set() 或者直接 s = {1, 2, 3}而不存在空的{}来定义的。
另外还有几种定义的方法;
#第一种:直接用dict()来定义
>>> d = dict(
... name='kidult',
... title='smart',
... age=21,
... )
>>> d
{'name': 'kidult', 'title': 'smart', 'age': 21}
#第二种:用{}
>>> d = {
... 'name':'kidult',
... 'title':'smart',
... 'age':21,
... }
>>> d
{'name': 'kidult', 'title': 'smart', 'age': 21}
>>> type(d)
<class 'dict'>
第三种有两点要求:
- 可迭代对象的元素必须是一个二元组
- 二元组的第0个元素是字典的key,第一个元素为字典的value
>>> d = dict([('a', 1), ('b', 2)])
>>> d
{'a': 1, 'b': 2}
还有一种初始化的方式,传入的可迭代对象元素为key,值为abc
>>> d = dict.fromkeys(range(5),'abc')
>>> d
{0: 'abc', 1: 'abc', 2: 'abc', 3: 'abc', 4: 'abc'}
#若第二个参数不写,则值为None
>>> d = dict.fromkeys(range(5))
>>> d
{0: None, 1: None, 2: None, 3: None, 4: None}
增加
可以直接使用key作为下标,对某个不存在的下标赋值,会增加key-value对
>>> d
{0: 'abc', 1: 'abc', 2: 'abc', 3: 'abc', 4: 'abc'}
>>> d['a'] = 'kidult学python'
>>> d
{0: 'abc', 1: 'abc', 2: 'abc', 3: 'abc', 4: 'abc', 'a': 'kidult学python'}
通过update方法可以同时更新多个键值对,甚至将一个新的字典更新到另一个字典里:
>>> d.update([('c', 3),('p', 0)])
>>> d
{0: 'abc', 1: 'abc', 2: 'abc', 3: 'abc', 4: 'abc', 'a': 'kidult学python', 'c': 3, 'p': 0}
update传入参数和dict一样,可以接受一个可迭代对象
如下操作也可:
>>> d = {}
>>> d.update({'age':21,'name':'kidult'})
>>> d
{'age': 21, 'name': 'kidult'}
#若存在相同的key就会修改字典,所有update通常用于合并字典
>>> d
{'age': 21, 'name': 'kidult'}
>>> d.update({'age':20, 'love':'python'})
>>> d
{'age': 20, 'name': 'kidult', 'love': 'python'}
修改
>>> d
{'age': 20, 'name': 'kidult', 'love': 'python'}
>>> d['age'] = 18
>>> d
{'age': 18, 'name': 'kidult', 'love': 'python'}
当key存在,对下标赋值的时候,会修改这个key对于的value。
删除
- dict.pop
>>> help(d.pop)
Help on built-in function pop:
pop(...) method of builtins.dict instance
D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised
看下pop的签名,和list不一样,dict.pop需要传入一个key,这个key是字典中的键,他会返回这个key的value。
在key不存在的情况下:如果传入了第二个参数d,那么就返回给你d,这里的d就是默认值default,否则抛出KeyError异常。
>>> d.pop('age')
18
>>> d
{'name': 'kidult', 'love': 'python'}
#key不存在时:
#1.定义了default
>>> d.pop('age', 'default')
'default'
#2.没有default,会抛出异常KeyError
>>> d.pop('age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'age'
- dict.popitem
>>> help(d.popitem)
Help on built-in function popitem:
popitem(...) method of builtins.dict instance
D.popitem() -> (k, v), remove and return some (key, value) pair as a
2-tuple; but raise KeyError if D is empty.
看签名解释是随机返回一个kv对的二元组。如果字典为空,就会返回KeyError
>>> d.popitem()
('love', 'python')
>>> d.popitem()
('name', 'kidult')
>>> d.popitem()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'popitem(): dictionary is empty'
- dict.clear
清空一个字典
>>> d
{'name': 'kidult', 'title': 'smart', 'age': 21}
>>> d.clear()
>>> d
{}
当一个字典已经为空时,clear()方法不会有任何反应,也不会抛出异常。
- del
>>> d
{'name': 'kidult', 'title': 'smart', 'age': 21}
>>> del d['title']
>>> d
{'name': 'kidult', 'age': 21}
del语句删除一个键的引用,相当于dict.pop('title')
,所有一般使用pop。
修改键值需要先删除再添加的方法。
访问
- 单个元素的访问
>>> d.update(d.fromkeys(range(2),'abc'))
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc'}
>>> d[0]
'abc'
当key不存在时会抛出KeyError。
get()方法访问不存在的key的时候返回None,事实上,返回的是一个默认值,只不过这个默认值是None:
>>> d.get('age')
21
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc'}
>>> d.get(2)
>>> d.get(2,'没有')
'没有'
d.setdefault()方法可以用来初始化一个有默认值的字典:
>>> help(d.setdefault)
Help on built-in function setdefault:
setdefault(key, default=None, /) method of builtins.dict instance
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
效果如下:
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc'}
>>> d.setdefault(2,'default')
'default'
#当字典里没有设置的默认key时,出现
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc', 2: 'default'}
>>> d[2] = 'haha'
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc', 2: 'haha'}
>>> d.setdefault(2,'default')
'haha'
#当字典里有设置的默认key时,不出现
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc', 2: 'haha'}
其实是先调用get(k,default),然后赋值,然后返回该值,如下:
def setdefault(d, k, default):
value = d.get(k,default)
d[k] = value
return value
访问单个元素,要么用下标,要么用get方法
- 字典的遍历
字典的元素都是成对出现的
>>> for x in d:
... print(x)
...
name
age
0
1
2
>>> d
{'name': 'kidult', 'age': 21, 0: 'abc', 1: 'abc', 2: 'haha'}
如上可知:直接用for in遍历字典,遍历的是字典的key
可以直接使用d.values()
的方式获取到字典的值
>>> d.values()
dict_values(['kidult', 21, 'abc', 'abc', 'haha'])
values会返回一个可迭代对象,元素是字典的所有value
>>> for v in d.values():
... print(v)
...
kidult
21
abc
abc
haha
而d.items()
可以返回元素为字典的所有kv对的可迭代对象:
>>> for k, v in d.items():
... print(k,': ',v)
...
name : kidult
age : 21
0 : abc
1 : abc
2 : haha
字典的限制
- 字典的key不能重复
- 字典的key需要可hash
>>> d[[1, 2, 3]] = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
- 字典也不能做字典的key
字典的变体
- 默认字典
>>> from collections import defaultdict
>>> d1 = {}
>>> d2 = defaultdict()
>>> d1
{}
>>> d2
defaultdict(None, {})
看下defaultdict的解释
>>> help(defaultdict)
Help on class defaultdict in module collections:
class defaultdict(builtins.dict)
| defaultdict(default_factory[, ...]) --> dict with default factory
|
| The default factory is called without arguments to produce
| a new value when a key is not present, in __getitem__ only.
| A defaultdict compares equal to a dict with the same items.
| All remaining arguments are treated the same as if they were
| passed to the dict constructor, including keyword arguments.
defaultdict初始化的时候,需要传入一个函数,这个函数也叫工厂函数
当我们使用下标访问一个key的时候,如果这个key不存在,defaultdict会自动调用初始化时传入的函数,生成一个对象作为这个key的value
如下:
#普通版本
d = {}
for k in range(3):
for v in range(3):
if k not in d.keys():
d[k] = []
d[k].append(v)
>>> d
{0: [0, 1, 2],
1: [0, 1, 2],
2: [0, 1, 2]}
#使用defaultdict
>>> d = defaultdict(list)
>>> for k in range(3):
... for v in range(3):
... d[k].append(v)
...
>>> d
defaultdict(<class 'list'>, {0: [0, 1, 2], 1: [0, 1, 2], 2: [0, 1, 2]})
使用defaultdict就不再需要去判断有没有值,因为没有值的时候,他会去找defaultdict初始化时候传入的list,那么初始化的时候就变成了一个空列表。
- 高阶函数
先定义一个工厂函数f,当我们将这个工厂函数传入defaultdict的时候,若值不存在,就会生成一个默认值,这个值就是‘a’,是工厂函数f返回的:
>>> def f():
... print('f is called')
... return 'a'
...
>>> d = defaultdict(f)
#这里因为xxx这个key并不存在,所有默认调用f将a赋值。
>>> d['xxx']
f is called
'a'
>>> d
defaultdict(<function f at 0x00000201116FDA68>, {'xxx': 'a'})
若是继续对字典d查询一次不存在的yyy这个键,会发现如下情况:
>>> d['yyy']
f is called
'a'
>>> d
defaultdict(<function f at 0x00000201116FDA68>, {'xxx': 'a', 'yyy': 'a'})
如上,发现值均被添加,若此时查询已有的xxx键,f则不会被调用了。
>>> d['xxx']
'a'
- 有序字典
>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d[0] = 3
>>> d[3] = 4
>>> d[1] = 5
>>> d
OrderedDict([(0, 3), (3, 4), (1, 5)])
>>> for k, v in d.items():
... print(k, ': ', v)
...
0 : 3
3 : 4
1 : 5
此时字典变得有序输出了。然而事实上python3.6之后字典都是有序的了。
Q:什么时候需要有序字典?
A:即是kv对,又需要顺序时。