dict和list就是Python倚天剑和屠龙刀,dict是一个key-value容器结构,通过一个键去查到对应的元素,就像知道某个人的身份证号,可以通过容器查到该人的姓名。如果不用对象的情况下,dict可以完成大部分简单的工作,所以dict在Python里面几乎是必定用到的一个容器。

dict是用花括号包围,里面是一对对键值对,用逗号隔开,一般键可以用字符串或者整型,而值可以是任意对象。

  1. 基本用法
    1.1 初始化

a = dict()

推荐下面的初始化方式

a = {}

关键词传参方式可以很好地初始化dict

a = dict(key=“value”)
 {“key”:“value”}

1.2 插入元素

a = {}
 a[“name”] = “Tom”
 a[1000] = 3
 print(a)
 {“name”:“Tom”, 1000:3}

1.3 访问元素

print(a[“name”])
 “Tome”
 print(a.get(“name”, “default_name”))
 “Tome”

如果用中括号访问不存在的键值对,会报错KeyError

print(a[“c”])

特别推荐使用get(key, default)来访问字典,访问不存在的key的时候不会报错,可以设置一个默认值返回,如果不传入default参数,就会默认返回None。最后,如果你的时间不是很紧张,并且又想快速的python提高,最重要的是不怕吃苦,建议你可以架尉♥信(同音):276 3177 065 ,那个真的很不错,很多人进步都很快,需要你不怕吃苦哦!大家可以去添加上看一下~

print(a.get(“c”))
 None
 print(a.get(1001, 0))
 0

1.4 删除元素

a = {“name”:“Tome”}
 del a[“name”]

删除不存在的key会报错,可以用"name" in a来测试一下

if “name” in a:
 del a[“name”]

1.5 迭代字典

iteritems()和items()基本一样效果,但数量大的话,iteritems()性能会更好,所以一般默认用前者就好。通过下面的方式去迭代元素。

for key, val in a.iteritems():
 print(key, val)

1.6 字典推导式

顾名思义和列表推导式差不多。直接看例子

a = [{“name”:“Tom”, “vote_num”: 1}, {“name”: “Mary”, “vote_num”:2}]

直接生成个字典,保存了名字和票数的关系。这样从数据库查出来记录后,直接这样生成一个字典方便查询对应的关键数据

b = {row.get(“name”): row.get(“vote_num”, 0) for row in a}
 {“Tom”: 1, “Mary”: 2}

1.7 获取字典数量

len(d)

1.8 判断key是否在字典里面

官方建议用in或者not in,不推荐使用has_key()了,因为前者语法更简洁。

if “name” in a:
 print(“exists name”)
 else:
 print(“not exists name”)

1.9 用另一个字典覆盖当前字典

update()这个方法很常用,往往我们不想直接在原字典上面修改或者想覆盖另一个字典多项值就会用到了,这个方法没有返回值,经常有人用错了。

a = {“a”:1}
 a.update({“a”: 2, “b”:1})
 print(a)
 {“a”:2, “b”:1}

错误用法

a = a.update({“a”:2 , “b”:1})

1.10 获取键列表

keys()和iterkeys()都是获取键列表,后者性能更好,一般推荐使用后者

for key in a.iterkeys():
 print(key, a.get(key))

1.11 获取值列表:

values()和itervalues()获取值列表,同理上面

for val in a.itervalues():
 print(val)

1.12 获取元组列表

items()和iteritems()获取一个键值对列表[(key1, val1), (key2, val2)],一般配合循环使用。

强调一下在使用这些iter前缀的函数的时候,在循环中都不要修改字典,因为这样会有问题。后面讲到迭代器和生成器再详细讲。最后,如果你的时间不是很紧张,并且又想快速的python提高,最重要的是不怕吃苦,建议你可以架尉♥信(同音):276 3177 065 ,那个真的很不错,很多人进步都很快,需要你不怕吃苦哦!大家可以去添加上看一下~
for循环出来的是无序的,如果想要按照插入的顺序输出用collections包的OrderedDict。
for key, val in a.iteritems():
 print(key, val)

这个常用的例子就是想对字典的元素进行排序,再降序输出:

uid=>{“vote_num”: 1, “name”: “Tom”}

a = {“1000”: {“vote_num”: 1, “name”: “Tom”}, “1001”: {“vote_num”: 2, “name”: “Mary”}}
 key_pairs = a.items()

lambda是个简短的函数表达式,v输入参数,冒号后面跟着是逻辑

按票数降序排序

key_pairs.sort(key=lambda v: v[1].get(“vote_num”, 0), reverse=True)
 print(key_pairs)
 [(“1001”, {“vote_num”: 2, “name”: “Mary”}), (“1000”, {“vote_num”: 1, “name”: “Tom”})]

然后按照票数降序输出

for (uid, info) in key_pairs:
 print(“uid: {0} vote_num: {1}”.format(uid, info.get(“vote_num”, 0)))
 uid: 1001 vote_num: 2
 uid: 1000 vote_num: 1
  1. 应用例子: 统计票数

就以一个统计票数的例子来应用一下字典,虽然有Counter和defaultdict,但我觉得很多地方还是要用到dict的,把dict掌握了,前面两个其实就很好理解和使用。

例子和之前list的数据类似,需求是2个:

统计每天的总票数
想知道每天有哪些用户收到票的

数据文件

UID day vote_num
1000 2019_10_20 3
1000 2019_10_21 2
1001 2019_10_21 10
1001 2019_10_22 5

代码

import os
 import sys
 def main():
 # 从命令行中获取文件名参数,argv[0]是程序文件名
 fname = sys.argv[1]
 # f是文件描述符
 f = open(fname, “r”)
 # 每天票数统计字典,key是日期字符串,value是总票数
 day_num_dict = {}
 # 每天用户统计字典,key是日期字符串,value是用户uid列表
 day_uids_dict = {}
 for i, line in enumerate(f):
 # 第一行略过
 if i == 0:
 continue
 uid, day, vote_num = line.strip().split(" ")
 # map函数循环每个元素,把元素传进int()方法作为参数,最后赋值给uid,和vote_num
 uid, vote_num = map(int, [uid, vote_num])
 # 记录每天的票数
 # 如果已经有这个票数记录
 if day in day_num_dict:
 day_num_dict[day] += vote_num
 else:
 day_num_dict[day] = vote_num
 # 记录uid
 # 如果不在dict有初始化,必须先初始化一个列表
 if day not in day_uids_dict:
 day_uids_dict[day] = []
 # 养成良好习惯,后面必定加else
 else:
 pass
 uids = day_uids_dict.get(day,[])
 uids.append(uid)
 # 输出每天的总票数
 for day, vnum in day_num_dict.iteritems():
 print(day, vnum)
 # 输出每天有哪些用户uid
 for day, uids in day_uids_dict.iteritems():
 print(day, uids)

代码解释:

从命令行读取参数和从文件读取数据前面已经提过了
day_num_dict和day_uids_dict这两个分别保存了每天的总票数和每天的uid列表。
day_num_dict用in语句来判断是否已经有这个key,没有先初始化,有的话就直+=,当然推荐使用defauiltdict,不需要判断是否有这个key都可以直接使用+=。
day_uids_dict就是不能用defaultdict来替代的,每个key对应一个list,所以想直接day_num_dict[day].append(vote_num)是不行的,所以还是得先判断存在了不。
if..else..语句后面再谈,养成良好的习惯,加else结尾就不容易出错。

代码运行结果:

(‘2019_10_22’, 5)
(‘2019_10_21’, 12)
(‘2019_10_20’, 3)
(‘2019_10_22’, [1001])
(‘2019_10_21’, [1000, 1001])
(‘2019_10_20’, [1000])

最后提一种黑科技,很多时候key都不止一个uid,假如我想快速查到某个用户某天的票数呢,这里key就涉及了两个元素,uid和day,那如何是好呢?在使用Redis的时候也可以用同样的原理。有些人会用多个字典,但我觉得字典里面嵌入字典来查比较麻烦,下面这种直观易懂。

其实就是把两个元素用分隔符隔开,变成一个字符串,多个元素也没关系

key = “{0}_{1}”.format(“1000”, “2019_10_24”)
 a = {}
 a[key] = 10

获取票数

uid = 1000
 day = “2019_10_24”
 cur_key = “{0}_{1}”.format(uid, day)
 print(a.get(key))