037-字典

字典的基本概念

字典用大括号括起来,里面有一个个的项(item键值对)。每一个项由键(key)和值(value)构成。

>>> dict1
{'Mary': 'pupil', 'James': 'junior high school student', 'Patricia': 'High school student', 'John': 'undergraduate', 'Linda': 'postgraduate', 'Robert': 'PhD'}

字典的键必须独一无二,值则不必。值可以取任何数据类型,但必须是不可变的,例如字符串、数字、元组、列表等。

>>> dict2 = {'呼保义':'宋江','豹子头':'林冲','花和尚':'鲁智深','天雄星':'林冲','豹子头':'李逵','阮氏三兄弟':('阮小二','阮小五','阮小七'),'梁山三俏':['扈三娘','孙二娘','顾大嫂']}
>>> dict2
{'呼保义': '宋江', '豹子头': '李逵', '花和尚': '鲁智深', '天雄星': '林冲', '阮氏三兄弟': ('阮小二', '阮小五', '阮小七'), '梁山三俏': ['扈三娘', '孙二娘', '顾大嫂']}
>>> 

豹子头这个key出现了两次,一次是林冲,一次是李逵,字典默认保存最后出现的值。因此'豹子头':'林冲'这一项就没有保存成功。

key不能为列表:

>>> dict4 = {1:'宋江',('及时雨','呼保义','天魁星'):'宋江',['宋公明','宋押司']:'宋江'}
Traceback (most recent call last):
  File "", line 1, in 
    dict4 = {1:'宋江',('及时雨','呼保义','天魁星'):'宋江',['宋公明','宋押司']:'宋江'}
TypeError: unhashable type: 'list'
>>> dict4 = {1:'宋江',('及时雨','呼保义','天魁星'):'宋江',('宋公明','宋押司'):'宋江'}
>>> dict4
{1: '宋江', ('及时雨', '呼保义', '天魁星'): '宋江', ('宋公明', '宋押司'): '宋江'}
>>> 

创建字典的方法有很多,罗列如下:

>>> a = dict(one=1,two=2,three=3)
>>> b = {'one':1,'two':2,'three':3}
>>> c = dict(zip(('one','two','three'),(1,2,3)))
>>> d = dict((('one',1),('two',2),('three',3)))
>>> e = dict({'one':1,'two':2,'three':3})
>>> a == b == c == d == e
True

五种方法创建出来的字典是完全相等的。

访问字典中的项的方式与访问序列的时候类似,只不过访问序列需要在[]内写上index的值,而访问字典则需要写上key。访问的时候,如果字典存在这个键值对,则返回值,如果不存在,则报错。

字典没有+和*操作,不支持两个字典之间的拼接,或者用*重复创建多个字典。

字典的内置方法

1. fromkeys(seq[,value])

fromkeys()方法用于创建并返回一个新的字典。他有两个参数,第一个是键,第二个是值。值可以为空,为空则返回None.

>>> dict5 = {}
>>> dict5.fromkeys((1,2,3))
{1: None, 2: None, 3: None}
>>> dict5.fromkeys((1,2,3),'numbers')
{1: 'numbers', 2: 'numbers', 3: 'numbers'}
>>> dict5.fromkeys((1,2,3),('numbers','decimals'))
{1: ('numbers', 'decimals'), 2: ('numbers', 'decimals'), 3: ('numbers', 'decimals')}

根据最后一个例子可以看出,fromkeys()方法中,value这个参数是唯一的,是一个整体。拿元组当seq,可以将元组的每一个元素都变成字典中的一个key,但如果拿元组当value,只会将整个元组当成value,并映射到每一个key里面。不会去进行一个多对多的映射。

而这个方法里面那个原本就存在的字典,其实没啥意义。

>>> dict5 = {}

>>> dict6 = {'呼保义':'宋江','玉麒麟':'卢俊义'}
>>> dict5.fromkeys((1,2,3)) == dict6.fromkeys((1,2,3))
True

呵呵,工具人上线。

2 keys(),values(),items()

这个比较好理解,dict.keys()就是把字典中的keys返回到结果中。返回的结果是什么类型呢?dict_keys类型。没错,他就是一个独立的类型。

>>> dict1 = {}
>>> dict1 = dict1.fromkeys(range(6),'赞')
>>> a = dict1.keys()
>>> a
dict_keys([0, 1, 2, 3, 4, 5])
>>> type(a)

>>> b = dict1.values()
>>> type(b)

>>> c = dict1.items()
>>> type(c)

>>> 

3 get(key[,default])

get()方法提供了更加友好的方式去访问字典。当键不存在的时候,get()方法并不会报错,只是默默地返回了一个None。如果你对None过敏,you have allergy about None.那么default参数可以让你自定义找不到内容时返回的内容。

>>> dict1
{0: '赞', 1: '赞', 2: '赞', 3: '赞', 4: '赞', 5: '赞'}
>>> dict1.get(6)
>>> dict1.get(6,'没找着,你换个key再试试!')
'没找着,你换个key再试试!'

4 clear()

清空词典。

注意,请不要使用给原字典重新命名的方式来清空字典。以免产生安全隐患。

>>> a = {'姓名':'小甲鱼','密码':'123456'}
>>> b = a
>>> b
{'姓名': '小甲鱼', '密码': '123456'}
>>> a = {}
>>> a
{}
>>> b
{'姓名': '小甲鱼', '密码': '123456'}
>>> 
---------------
>>> 
>>> a = {'姓名':'小甲鱼','密码':'123456'}
>>> b = a
>>> b
{'姓名': '小甲鱼', '密码': '123456'}
>>> a.clear()
>>> a
{}
>>> b
{}

5 copy()

使用copy()方法创建一个原字典的浅拷贝。所谓的浅拷贝,就是在内存中新建一个新的,内容一样的字典。举例如下:

>>> a = {'姓名':'小甲鱼','密码':'123456'}
>>> b = a
>>> b
{'姓名': '小甲鱼', '密码': '123456'}
>>> c = a.copy()
>>> c
{'姓名': '小甲鱼', '密码': '123456'}
>>> a['姓名'] = '老污龟'
>>> a
{'姓名': '老污龟', '密码': '123456'}
>>> b
{'姓名': '老污龟', '密码': '123456'}
>>> c
{'姓名': '小甲鱼', '密码': '123456'}

可以看到,浅拷贝和直接赋值的区别。看到这里我产生了一个疑惑:

>>> a = {'姓名':'小甲鱼','密码':'123456'}
>>> b = a
>>> b
{'姓名': '小甲鱼', '密码': '123456'}
>>> c = a.copy()
>>> c
{'姓名': '小甲鱼', '密码': '123456'}
>>> a = {}
>>> a
{}
>>> b
{'姓名': '老污龟', '密码': '123456'}
>>> c
{'姓名': '小甲鱼', '密码': '123456'}

还记得在clear()方法中的举例。同样是b = a,为什么修改的时候,b跟着a一起改变,而把a重新赋值的时候,b就不会跟着一起变呢?我们尝试着画一下图:


6 pop(key[,default])和popitem()

pop就是弹出,弹掉的意思。参考弹烟灰的动作。

dict.pop(key)就是把字典里指定key所在的item弹出,并返回这个key对应的value。而dict.popitem()则是直接弹出最后一个item,并返回这个item。例:

>>> dict1 = dict(((1,'I'),(2,'II'),(3,'III'),(4,'IV')))
>>> dict1
{1: 'I', 2: 'II', 3: 'III', 4: 'IV'}
>>> dict1.pop(2)
'II'
>>> dict1
{1: 'I', 3: 'III', 4: 'IV'}
>>> dict1.popitem()
(4, 'IV')
>>> dict1
{1: 'I', 3: 'III'}

7 setdefault(key[,default])

他相当于根据key查找value,如果存在,就返回,如果不存在,就将default存进去,如果未定义default,则将None存进去。

>>> dict1 = dict(((1,'I'),(2,'II'),(3,'III'),(4,'IV')))
>>> dict1
{1: 'I', 2: 'II', 3: 'III', 4: 'IV'}
>>> dict1.setdefault(3)
'III'
>>> dict1
{1: 'I', 2: 'II', 3: 'III', 4: 'IV'}
>>> dict1.setdefault(5,'V')
'V'
>>> dict1
{1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V'}

8 update([other])

update()用来更新更新字典,也就是修改和添加item的操作。

>>> dict2 = dict((('呼保义','宋江'),('玉麒麟','卢俊义'),('豹子头','林冲'),('浪子','李逵')))
>>> dict2
{'呼保义': '宋江', '玉麒麟': '卢俊义', '豹子头': '林冲', '浪子': '李逵'}
>>> dict2.update(浪子='燕青')
>>> dict2
{'呼保义': '宋江', '玉麒麟': '卢俊义', '豹子头': '林冲', '浪子': '燕青'}
>>> dict2.update(黑旋风='李逵')
>>> dict2
{'呼保义': '宋江', '玉麒麟': '卢俊义', '豹子头': '林冲', '浪子': '燕青', '黑旋风': '李逵'}

然而在另外一个例子中,却发现了问题:

>>> dict1
{1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V'}
>>> dict1.update(6='VI')
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?

为什么会出现这样的情况呢?研究一下报错提示:expression cannot contain assignment(表达式不能包含赋值操作)

仔细研究一下,updata()方法括号当中的内容,6='VI',有没有觉得有点眼熟?
没错,它本质上是一个赋值操作。还记得我们最早讲到的,变量不能是数字的要求吗?

因此,如果使用update()方法来修改或者添加字典的项,一定注意,这个字典的key不能是数字,否则就会出现这样的错误。

我们之前在讲函数的收集参数的时候提到过,定义函数时,形参如果使用一个*,那么它表示将参数打包成一个元组,使用两个*,形参会被打包成一个字典。而在实参中,如果使用一个*,则元组会被解包,字典也一样。

举例如下:

>>> def test(**params):
    print('一共有%d个参数' % len(params))
    print('他们分别是:',params)

    
>>> test(a=1,b=2,c=3,d=4,e=5)
一共有5个参数
他们分别是: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> a = {'呼保义': '宋江', '玉麒麟': '卢俊义', '豹子头': '林冲', '浪子': '燕青', '黑旋风': '李逵'}
>>> test(**a)
一共有5个参数
他们分别是: {'呼保义': '宋江', '玉麒麟': '卢俊义', '豹子头': '林冲', '浪子': '燕青', '黑旋风': '李逵'}

-------------------------

>>> def test(*params):
    print('一共有%d个参数' % len(params))
    print('他们分别是:',params)

    
>>> test('宋江','卢俊义','林冲','燕青','李逵')
一共有5个参数
他们分别是: ('宋江', '卢俊义', '林冲', '燕青', '李逵')
>>> test(*('宋江', '卢俊义', '林冲', '燕青', '李逵'))
一共有5个参数
他们分别是: ('宋江', '卢俊义', '林冲', '燕青', '李逵')

你可能感兴趣的:(037-字典)