记录学习《流畅的python》的一些知识-----字典和集合(2)

记录我学习《流畅的python》的过程

    • 2020.12.29

2020.12.29

1.映射的弹性键查询,defaultdict-处理找不到的键的一个选择
在创建defaultdict对象的时候,就需要给它配置一个为找不到的键创造默认值的方法。

"""创建一个从单词到其出现情况的映射"""

import sys
import re
import collections

WORD_RE = re.compile(r'\w+')

index = collections.defaultdict(list)

with open(sys.argv[1], encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
        for match in WORD_RE.finditer(line):
            word = match.group()
            column_no = match.start()+1
            location = (line_no, column_no)
            index[word].append(location)
# 以字母顺序打印出结果
for word in sorted(index, key=str.upper):
    print(word, index[word])

运行结果(待解决):
在这里插入图片描述

2.特殊方法__missing__
所有的映射类型在处理找不到的键的时候,都会牵扯到__missing__方法。如果有一个类继承了dict,然后这个继承类提供了__missing__方法,那么在__getitem__碰到找不到的键的时候,Python就会自动调用它,而不是抛出一个KeyError异常。
例:有时候会希望在查询的时候,映射类型里的键统统转换成str。

class StrKeyDict0(dict): # StrKeyDict0继承了dict

    def __missing__(self, key):
        if isinstance(key, str): # 如果找不到的键本身就是字符串,那就抛出KeyError异常
            raise KeyError(key)
        return self[str(key)] # 如果找不到的键不是字符串,那么就把它转换成字符串在进行查找

    def get(self, key, default=None):
        try:
            """
            get方法把查找工作用self[key]的形式委托给__getitem__,这样在
            宣布查找失败时,还能通过__missing__再给某个键一个机会
            """
            return self[key]
        except KeyError:
            return default #如果抛出KeyError, 那么说明__missing__也失败了,返回default

    def __contains__(self, key):
        """
        先按照传入键的原本的值来查找(映射中可能含有非字符串的键),如果
        没有找到,再用str方法把键转换成字符串在查找一次
        """
        return key in self.keys() or str (key) in self.keys()

# tests for item retrieval using 'd[key]' notation::

d = StrKeyDict0([('2', 'two'), ('4', 'four')])
print(d['2'])

print(d[4])

# tests for item retrieval using 'd.get[key]' notation::

print(d.get('2'))
print(d.get(4))
print(d.get(1, 'N\A'))

# Tests for the 'in' operator::

print(2 in d)
print(1 in d)

运行结果:
在这里插入图片描述
3.字典的变种
collections.OrderedDict
这个类型再添加键的时候会保持顺序,因此键的迭代次序总是一致的。
collections.ChainMap
该类型可以容纳数个不用的映射对象,然后在进行键查找操作的时候,这些对象会被当做一个整体被逐个查找,直到键被找到为止。
collections.Counter
这个映射类型会给键准备一个整数计时器。

import collections

ct = collections.Counter('abracadabra')
print(ct)

ct.update('aaaaazzz')
print(ct)

print(ct.most_common(3))# 自己理解为最常出现的

运行结果:
在这里插入图片描述
collections.UserDict
把标准dict用纯Python又实现了一遍。
对__missing__方法中StrKeyDic类的优化:

import collections

class StrKeyDict(collections.UserDict):
    
    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError(key)
        return  self[str(key)]
    
    def __contains__(self, key):
        return str(key) in self.data
    
    def __setitem__(self, key, item):
        self.data[str(key)] = item

4.不可变映射类型
types模块中引入了一个封装名叫MappingProxyType。如果给这个类一个映射,它会返回一个只读的映射视图。

from types import MappingProxyType
d = {
     1:'A'}
d_proxy = MappingProxyType(d)
print(d_proxy)

print(d_proxy[1])

d_proxy[2] = 'x'

d[2] = 'B'
print(d_proxy)

运行结果:
记录学习《流畅的python》的一些知识-----字典和集合(2)_第1张图片
不允许做任何修改
删除d_proxy[2] = 'x’后
运行结果:
在这里插入图片描述
对d的修改会反馈到d_proxy上。
5.集合论
集合的本质是许多唯一对象的聚集。因此,集合可以用于去重:

l = ['spam', 'spam', 'eggs', 'eggs']
print(set(l))
print(list(set(l)))

运行结果:
在这里插入图片描述
除了保证唯一性,集合还实现了很多基础的中缀运算符。a | b返回合集,a & b返回交集,a - b返回差集。
查找needles的元素在haysack里出现的次数。

needles_0 = ['s', 'a', 'b', 'd']
haystack_0 = ['s', 'c', 'd', 'a', 'b', 'f']
needles = set(needles_0)
haystack = set(haystack_0)
found = len(needles & haystack)
print(found)

运行结果:
在这里插入图片描述
如果不使用交集操作,就会变成如下代码:

needles_0 = ['s', 'a', 'b', 'd']
haystack_0 = ['s', 'c', 'd', 'a', 'b', 'f']
needles = set(needles_0)
haystack = set(haystack_0)
found = 0
for n in needles:
    if n in haystack:
        found += 1
print(found)

运行结果一样。
6.集合字面量
除空集之外,集合的字面量-{1},{1,2},等等——看起来它的数学形式一模一样。如果是空集,那么必须写成set()的形式。

s = {
     1}
print(type(s))
print(s)
print(s.pop())
print(s)

运行结果:
在这里插入图片描述

字面量方法和构造方法的不同:

from dis import dis
print(dis('{1}'))

print(dis('set([1])'))

运行结果:
记录学习《流畅的python》的一些知识-----字典和集合(2)_第2张图片
7.集合推导

from unicodedata import  name
print({
     chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i), '')})

运行结果:
在这里插入图片描述
8.dict的实现及其导致的结果
将同样的数据以不同的顺序添加到3个字典里:

DIAL_CODES = [
    (86, 'China'),
    (91, 'India'),
    (1, 'United States'),
    (62, 'Indonesia'),
    (55, 'Brazil'),
    (92, 'Pakistan'),
    (880, 'Bangladesh'),
    (234, 'Nigeria'),
    (7, 'Russia'),
    (81 , 'Japan'),
]

d1 = dict(DIAL_CODES)
print('d1:', d1.keys())
d2 = dict(sorted(DIAL_CODES))
print('d2:', d2.keys())
d3 = dict(sorted(DIAL_CODES, key=lambda x:x[1]))
print('d3:', d3.keys())

运行结果:
在这里插入图片描述

你可能感兴趣的:(python,字典,集合,集合论)