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一起走。