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 "<pyshell#48>", line 1, in <module>
    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)
<class 'dict_keys'>
>>> b = dict1.values()
>>> type(b)
<class 'dict_values'>
>>> c = dict1.items()
>>> type(c)
<class 'dict_items'>
>>> 

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个参数
他们分别是: ('宋江', '卢俊义', '林冲', '燕青', '李逵')
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容