字典推导式--模式匹配处理映射--可哈希的定义--字典get()方法优化--__missing__方法

1.字典推导式的引入

        对于python的学习者肯定都知道列表推导式,但衍生的还有字典推导式等等,这里摆下字典推导式如何创建和使用的样例

 

#首先创建数据
dial_codes=[
    (800,'Bangladesh'),
    (55,'Brazil'),
    (86,'China'),
    (91,'India'),
    (62,'Indonesia'),
    (81,'Japan'),
    (234,'Nigeria'),
    (92,'Pakistan'),
    (7,'Russia'),
    (1,'United Status')
]

#字典推导式(和列表推导式大同小异)
country_dial={country:code for code,country in dial_codes}
print(country_dial)

 

"""字典推导式的应用"""

#按照国家的键进行排序,把国家名称变成大写,选取code小于70的
{code:country.upper() for country,code in sorted(country_dial.items()) if code<70}

2. 模式匹配处理映射

         下面举出,从不同类型字典中提取出作者的名字的模式匹配案例,对于大数据清洗方面比较有用。

        和序列匹配一样,同样使用的是match和case语法

"""对于大数据方向的数据清洗,提取作者名字"""

def get_creators(record:dict)->list:
    match record:
        case {'type':'book','api':2,'authors':[*names]}:    #authors映射一个序列对象
            return names
        case {'type':'book','api':1,'author':name}:         #author映射一个任何对象
            return name                        
        case {'type':'movie','director':name}:
            return name
        case {'type':'book'}:
            raise ValueError(f'Invalid "book" record:{record!r}')
        case _:
            raise ValueError(f'Invalid "book" record:{record!r}')
            

"""
    第一条case语句:用于匹配字典类型为{'type':'book','api':2,'authors':'Mike Lisa '.split()}
    
    第二条case语句:用于匹配字典类型为{'type':'book','api':1,'author':'Mike'}

    第三条case语句:用于匹配字典类型为{'type':'movie','director':name}

    第四条case语句:用于匹配字典类型为{'type':'book'}
    
    第五条case语句:匹配其他字典类型

"""
#测试案例
"""与序列模式匹配不同,这里即便有多余的title——当部分满足也能匹配"""
b1=dict(api=1,author='Douglas Hofstadter',type='book',title='Godel,Escher,Bach')
get_creators(b1)


#'Douglas Hofstadter'
#我们发现匹配到了一个作者的名字,  
#测试样例2

#注意模式中的键无关紧要,即便是我们的顺序字典

from collections import OrderedDict
b2=OrderedDict(api=2,type='book',title='Python in a Nutshell',authors='Martelli Ravenscroft Holden'.split())

get_creators(b2)


#这次匹配上的是列表类型的作者名字
#['Martelli', 'Ravenscroft', 'Holden']
#测试样例3

#不符合任何一条匹配作者姓名的case语句,抛出错误
get_creators({'type':'book','pages':770})


"""
    ValueError: Invalid "book" record:{'type': 'book', 'pages': 770}

"""
 (1)匹配多余的键值对
"""
    匹配多余的键值对,使用**kwargs进行匹配

"""

food=dict(category='ice cream',flavor='vanilla',cost=99)
match food:
    case {'category':'ice cream',**kwargs}:
        print(kwargs)
    case _:
        raise ValueError(f'No detals')

"""
    {'flavor': 'vanilla', 'cost': 99}

"""

 3.可哈希的定义

"""
    数值类型以及不可变的扁平类型str和bytes都是可以哈希的,如果容器类型是不可变的,而且所含的对象全是可哈希的,那么容器类型自身也是可哈希的

"""

下面举几个简单的例子辅助各位理解什么是可以哈希的

"""
tt是一个元组,它的元素中也有一个元组,那个元组一样不可变,所以tt可以hash
"""

tt=(1,2,(30,40))
hash(tt)

"""
    哈希值为:-3907003130834322577
"""
"""
tl本身是一个元组,满足哈希性,但是它的元素有一个列表,可以通过tl[2].extend()进行改变,所以tl现在不满足哈希性质
"""

tl=(1,2,[30,40])
hash(tl)

"""
    TypeError                                 Traceback (most recent call last)
Cell In[47], line 3
      1 #tl本身是一个元组,满足哈希性,但是它的元素有一个列表,可以通过tl[2].extend()进行改变,所以tl现在不满足哈希性质
      2 tl=(1,2,[30,40])
----> 3 hash(tl)

TypeError: unhashable type: 'list'

"""
#frozenset
"""
    frozenset() 是 Python 中的一个内置函数,用于创建不可变的集合(frozenset)。和普通的集合不同,不可变集合是不可变的,意味着一旦创建,就不能更改其内容,也不能添加或删除元素。
"""

tf=(1,2,frozenset([30,40]))
hash(tf)

"""所以frozenset方法所构造的都是是可以hash的"""

 4.字典get()方法优化

对于提取字典中的键值对,我们一般使用的是dict[key]获取value参数,如果没有key这个键则会报错,所以有以下三种方法,防止报错和优化代码

优化:

        1.dict.get(key,default_value)

        2.dict.setdefault(key,default_value)

        3.使用collections.defaultdict(list)方法

PS:下面重点注意虚线下方的代码

(1)dict.get(key,default_value)

import re
import sys

#直接创建正则对象
WORD_RE=re.compile(r'\w+')

index={}
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)

"""------------------------------------------------------------"""
            occurrences=index.get(word,[])
            occurrences.append(locataion)
            index[word]=occurrences

"""
    1.如果index没有匹配到word参数,则返回空列表
    2.空列表append添加locations地址
    3.index[word]更新或者添加[location]
"""


(2)dict.setdefault(key,default_value)

import re
import sys

#直接创建正则对象
WORD_RE=re.compile(r'\w+')

index={}
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.setdefault(word,[]).append(location)
"""
    1.如果index没有匹配到word参数,则返回空列表给index[word]
    2.index[word]使用append方法添加location参数
    
"""


(3) 使用collections.defaultdict(list)方法
#defaultdict处理缺失键的另一种选择

"""
    当没有存在key键时,defaultdict的运行:
    1调用list()创建一个新列表
    2把该列表插入dd,对应到new-key键上
    3返回该列表的引用

"""
import collections
import re
import sys

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

#如果dict()[key]方法没有对应的键,自动生成一个列表,并放入其中

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=(line_no,column_no)
            index[word].append(location)

#现将所有的键值按照大写进行排序,返回新的字典,再遍历,print(键,字典{键})
for word in sorted(index,key=str.upper):
    print(word,index[word])

5.自定义字典的__missing__方法

 自己编写一个字典类,完善调用dict[key]时没有找到key键的__missing__方法.

class StrKeyDict(dict):
    
    #如果传入的key不是字符串,且没有在字典中找到该键,将调用str(key),又进行查找该键,如果仍然没有则抛出错误

    def __missing__(self,key):
        if isinstance(key,str):
            raise KeyError(key)
        return self[str(key)]

    
    def get(self,key,default=None):
        try:
            return self[key]
        except KeyError:
            return default

    #判定key是否存在于dict的键中,----str方法考虑的周到
    def __contains__(self,key):
        return key in self.keys() or str(key) in self.keys()
错误测试样例
d=StrKeyDict({2:'two','4':'four'})
d['2']

"""
    报错原因没有匹配到对应的键,抛出ValueError错误
"""


"""
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[69], line 2
      1 d=StrKeyDict({2:'two','4':'four'})
----> 2 d['2']

Cell In[66], line 6, in StrKeyDict.__missing__(self, key)
      4 def __missing__(self,key):
      5     if isinstance(key,str):
----> 6         raise KeyError(key)
      7     return self[str(key)]

KeyError: '2'

"""
正确测试样例
 

该自定义字典类的思维导图 

 

 跟着小py开拓未来的道路,各位uu一起走。

 

 

 

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烧酒调调

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值