8、Python3 字典应用

作者: Brinnatt 分类: python 术 发布时间: 2023-03-30 10:01
  • key-value 键值对的数据的集合
  • 可变的 、 无序的 、 key 不重复

8.1、字典 dict 定义

  • d = dict() 或者 d = {}
  • dict(**kwargs) 使用 name=value 对初始化一个字典
  • dict(iterable, **kwarg) 使用可迭代对象和 name=value 对构造字典,不过可迭代对象的元素必须是一个 二元 结构
  • dict(mapping, **kwarg) 使用一个字典构建另一个字典
  • d = {'a':10, 'b':20, 'c':None, 'd':[1,2,3]}
d1 = {'a':1,'b':2}
print(d1)

d2 = dict(a=1,b=2)
print(d2)

d3 = dict((('a',1),('b',2)))
print(d3)

d4 = dict([['a',1],['b',2]])
print(d4)

d5 = dict(('a',1))
print(d5)

输出结果:
{'b': 2, 'a': 1}
{'b': 2, 'a': 1}
{'b': 2, 'a': 1}
{'b': 2, 'a': 1}
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-42-e43e2441f817> in <module>
     11 print(d4)
     12
---> 13 d5 = dict(('a',1))
     14 print(d5)

ValueError: dictionary update sequence element #0 has length 1; 2 is required

注:最后这个异常是因为,dict 后面接可迭代对象,可迭代对象中必须是二元组,所以只能像上面几种,用嵌套做到。
  • 类方法 dict.fromkeys(iterable, value)
d1 = dict.fromkeys(range(5))
print(d1)

d2 = dict.fromkeys(range(5),10)
print(d2)

d3 = dict.fromkeys(range(5),[10])
print(d3)
print(id(d3[0]))
print(id(d3[1]))

d3[0][0]=20
print(d3)

输出结果:
{0: None, 1: None, 2: None, 3: None, 4: None}
{0: 10, 1: 10, 2: 10, 3: 10, 4: 10}
{0: [10], 1: [10], 2: [10], 3: [10], 4: [10]}
1648769246600
1648769246600
{0: [20], 1: [20], 2: [20], 3: [20], 4: [20]}

8.2、字典元素的访问

8.2.1、d[key]

  • 返回key对应的值value
  • key不存在抛出KeyError异常
d = {'a':1,'b':2,'c':3}
print(d['a'])
print(d['d'])
--------------------------------------------
1
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-54-60a384469287> in <module>
      1 d = {'a':1,'b':2,'c':3}
      2 print(d['a'])
----> 3 print(d['d'])

KeyError: 'd'

8.2.2、get(key[, default])

  • 返回key对应的值value
  • key不存在返回缺省值,如果没有设置缺省值就返回None
d = {'a':1,'b':2,'c':3}
print(d.get('a'))
print(d.get('d'))
print(d.get('d','substitude'))
--------------------------------------------
1
None
substitude

8.2.3、setdefault(key[, default])

  • 返回 key 对应的值 value
  • key 不存在,添加 kv 对,value 为 default,并返回 default,如果 default 没有设置,缺省为 None
d = {'a':1,'b':2,'c':3}
print(d.setdefault('a'))
print(d.setdefault('d','substitude'))
print(d)

输出结果:
1
substitude
{'d': 'substitude', 'c': 3, 'b': 2, 'a': 1}

8.3、字典增加和修改

8.3.1、d[key] = value

  • 将key对应的值修改为value
  • key不存在添加新的kv对

8.3.2、update([other]) -> None

  • 使用另一个字典的kv对更新本字典
  • key不存在,就添加
  • key存在,覆盖已经存在的key对应的值
  • 就地修改
print(d)
d.update(red=1)
d.update((('red',2),))
d.update({'red':3})
print(d)

输出结果:
{'d': 'substitude', 'c': 3, 'b': 2, 'a': 1}
{'d': 'substitude', 'red': 3, 'a': 1, 'c': 3, 'b': 2}

8.4、字典删除

8.4.1、pop(key[, default])

  • key存在,移除它,并返回它的value
  • key不存在,返回给定的default
  • default未设置,key不存在则抛出KeyError异常
d = {'a':1,'b':2,'c':3}
print(d.pop('d','nothing'))
print(d.pop('d'))

输出结果:
nothing
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-80-2e770a681a96> in <module>
      1 d = {'a':1,'b':2,'c':3}
      2 print(d.pop('d','nothing'))
----> 3 print(d.pop('d'))

KeyError: 'd'

8.4.2、popitem()

  • 移除并返回一个任意的键值对
  • 字典为 empty,抛出 KeyError 异常
d = {'a':1,'b':2,'c':3}
print(d.popitem())
print(d.popitem())
print(d.popitem())
print(d.popitem())

输出结果:
('c', 3)
('b', 2)
('a', 1)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-84-755869381dc0> in <module>
      3 print(d.popitem())
      4 print(d.popitem())
----> 5 print(d.popitem())

KeyError: 'popitem(): dictionary is empty'

8.4.3、clear()

  • 清空字典

8.4.4、del 语句

d = {'a': 1, 'b': 2, 'c': 3, 'd': 'substitude', 'red': 3}
c = d
print(c)
print(d)

del(d['a'])
print(c)
print(d)

del(d)
print(c)

输出结果:
{'red': 3, 'd': 'substitude', 'c': 3, 'b': 2, 'a': 1}
{'red': 3, 'd': 'substitude', 'c': 3, 'b': 2, 'a': 1}
{'red': 3, 'd': 'substitude', 'c': 3, 'b': 2}
{'red': 3, 'd': 'substitude', 'c': 3, 'b': 2}
{'red': 3, 'd': 'substitude', 'c': 3, 'b': 2}

注:del a['c'] 看着像删除了一个对象,本质上减少了一个对象的引用,del 实际上删除的是名称,而不是对象,对象由GC处理,另外一定要熟悉内存中深浅拷贝的本质。

8.5、字典遍历

8.5.1、遍历 key

for k in d:
    print(k)

for k in d.keys():
    print(k)

8.5.2、遍历 value

for k in d:
    print(d[k])

for k in d.keys():
    print(d.get(k))

for v in d.values():
    print(v)

8.5.3、遍历 item,即 kv 对

for item in d.items():
    print(item)

for item in d.items():
    print(item[0], item[1])

for k,v in d.items():
    print(k, v)

for k, _ in d.items():
    print(k)

for _ ,v in d.items():
    print(v)

8.5.4、总结

  • Python3 中,keys、values、items 方法返回一个类似一个生成器的可迭代对象,不会把函数的返回结果复制到内存中。
    • Dictionary view 对象。
    • 字典的 entry 的动态的视图,字典变化,视图将反映出这些变化。
  • Python2 中,上面的方法会返回一个新的列表,占据新的内存空间。所以 Python2 建议使用 iterkeys、itervalues、iteritems 版本,返回一个迭代器,而不是一个 copy。

8.6、字典遍历和移除

如何在遍历的时候移除元素?

# 错误的做法
d = dict(a=1, b=2, c='abc')
for k,v in d.items():
    d.pop(k) # 异常
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-12-0f05b4388341> in <module>
      1 d = dict(a=1, b=2, c='abc')
----> 2 for k,v in d.items():
      3     d.pop(k) # 异常

RuntimeError: dictionary changed size during iteration

while len(d): # 相当于清空,不如直接clear()
    print(d.popitem())
# 正确的做法
d = dict(a=1, b=2, c='abc')
keys = []
for k,v in d.items():
    if isinstance(v, str):
        keys.append(k)

for k in keys:
    d.pop(k)
print(d)

8.7、字典的 key

key 的要求和 set 的元素要求一致:

  • set 的元素可以就是看做 key,set 可以看做 dict 的简化版。
  • hashable 可哈希才可以作为 key,可以使用 hash() 测试。
  • d = {1 : 0, 2.0 : 3, "abc" : None, ('hello', 'world', 'python') : "string", b'abc' : '135'}。

8.8、defaultdict

collections.defaultdict([default_factory[, ...]])

  • 第一个参数是 default_factory,缺省是 None,它提供一个初始化函数。当 key 不存在的时候,会调用这个工厂函数来生成 key 对应的 value
import random
d1 = {}
for k in 'abcdef':
    for i in range(random.randint(1,5)):
        if k not in d1.keys():
            d1[k] = []
        d1[k].append(i)
print(d1)

对比:

from collections import defaultdict
import random

d1 = defaultdict(list)
for k in 'abcdef':
    for i in range(random.randint(1,5)):
        d1[k].append(i)
print(d1)

8.9、OrderedDict

collections.OrderedDict([items])

  • key 并不是按照加入的顺序排列,可以使用 OrderedDict 记录顺序。
from collections import OrderedDict
import random
d = {'banana':3,'apple':4,'pear':1,'orange':2}
print(d)
keys = list(d.keys())
random.shuffle(keys)
print(keys)
od = OrderedDict()
for key in keys:
    od[key] = d[key]
print(od)
print(od.keys())
----------------------------------------------------------------
{'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
['apple', 'pear', 'banana', 'orange']
OrderedDict([('apple', 4), ('pear', 1), ('banana', 3), ('orange', 2)])
odict_keys(['apple', 'pear', 'banana', 'orange'])
  • 有序字典可以记录元素插入的顺序,打印的时候也是按照这个顺序输出打印
  • 3.6 版本的 Python 的字典就是记录 key 插入的顺序(IPython 不一定有效果)
  • 应用场景:
    • 假如使用字典记录了N个产品,这些产品使用ID由小到大加入到字典中
    • 除了使用字典检索的遍历,有时候需要取出ID,但是希望是按照输入的顺序,因为输入顺序是有序的
    • 否则还需要重新把遍历到的值排序

8.10、练习

用户输入一个数字,打印每一位数字及其重复的次数。

num = input(">>>")
d = {}
for c in num:
    if not d.get(c):
        d[c] = 1
        continue
    d[c] += 1
print(d)

num = input(">>>")
d = {}
for c in num:
    if c not in d.keys():
        d[c] = 1
    else:
        d[c] += 1
print(d)

数字重复统计,随机产生100个整数,数字的范围[-1000,1000],升序输出所有不同的数字及其重复的次数。

import random

n = 100

nums = [0] * n
for i in range(n):
    nums[i] = random.randint(-1000,1000)
print(nums)
t = nums.copy()
t.sort()
print(t)
print("===========================================")

d = {}
for x in nums:
    if x not in d.keys():
        d[x] = 1
    else:
        d[x] += 1
print(d)
print("===========================================")

d1 = sorted(d.items())
print(d1)
print("===========================================")

字符串重复统计,字符表"abcdefghijklmnopqrstuvwxyz",随机挑选2个字母组成字符串,共挑选100个,降序输出这100个字符串及重复的次数。

import random

alphabet = 'abcdefghijklmnopqrstuvwxyz'

words = []

for _ in range(100):
    words.append(random.choice(alphabet)+random.choice(alphabet))

d = {}

for x in words:
    d[x] = d.get(x,0) + 1
print(d)

d1 = sorted(d.items(),reverse=True)
print(d1)
标签云