python setdefault函数_Python——用setdefault处理找不到的键

注:对《流畅的python》第三章,用setdefault处理找不到的键,的解析

当字典 d[k] 不能找到正确的键的时候,Python 会抛出异常。

也许可以用 d.get(k, default) 来代替 d[k],给找不到的键一个默认的返回值(这比处理 KeyError 要方便不少)。但是要更新某个键对应的值的时候,不管使用__getitem__还是 get都会不自然,而且效率低。就像示例 3-2 中的还没有经过优化的代码所显示的那样,dict.get并不是处理找不到的键的最好方法。

一般的解决方法

示例 3-2 这段程序从索引中获取单词出现的频率信

息,并把它们写进对应的列表里

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

import sys

import re

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, [])

#通过get函数,获得字典里word对应的值,如果没找到word(还没有记录),则返回[]

occurrences.append(location) #将单词的位置加到位置list的后面

index[word] = occurrences #将字典中word对应的列表进行更新

# 以字母顺序打印出结果

for word in sorted(index, key=str.upper):

print(word, index[word])

示例 3-3 这里是示例3-2 的不完全输出,每一行的列表都代表一

个单词的出现情况,列表中的元素是一对值,第一个值表示出现的

行,第二个表示出现的列

$ python3 index0.py ../../data/zen.txt

a [(19, 48), (20, 53)]

Although [(11, 1), (16, 1), (18, 1)]

ambiguity [(14, 16)]

be [(15, 14), (16, 27), (20, 50)]

Beautiful [(3, 1)]

...

❶'\w+'正则表达式

正则表达式中的'\w+'

(1)对于Unicode(str类型)模式:匹配任何Unicode的单词字符,基本上所有语言的字符都可以匹配,当然也包括数字和下划线;如果开启了re.ASCII标志,就只匹配[a-zA-Z0-9]

(2)对于8位(bytes类型)模式:匹配ASCII中定义的字母数字,即[a-zA-Z0-9]

此处我觉得应该就是(2)

❷sys.argv

sys.argv是传递给Python脚本的命令行参数列表。argv[0]是脚本名称(依赖于操作系统,无论这是否是完整路径名)。如果使用-c解释器的命令行选项执行命令,argv[0]则将其设置为字符串' -c'。如果没有脚本名称传递给Python解释器,argv[0]则为空字符串。

举例

$ python hello.py

>>> print(sys.agrv)

['hello.py']

$ python hello.py world

>>> print(sys.argv)

['hello.py', 'world']

$ python hello.py world hello

>>> print(sys.argv)

['hello.py', 'world', 'hello']

with open(sys.argv[1], encoding='utf-8') as fp这句话就是以utf-8文件模式打开sys.argv[1]文件,将文件开头的位置传给fp参数

❸enumerate()函数

enumerate()函数用于将一个可遍历的数据对象(如字符串、元组、列表)组合成一个索引序列,同时列出数据下标和数据(一般用在for循环当中)

语法:enumerate(seq, [start =0])

seq:一个序列、迭代器或其他支持迭代对象

start:下标起始的位置(一般默认为0)

>>> number = ['one', 'two', 'three']

>>> list(enumerate(number))

[(0, 'one'), (1, 'two'), (2, 'three')]

>>> list(enumerate(number, start = 2))

[(2, 'one'), (3, 'two'), (4, 'three')]

#for 循环使用enumerate

>>> for i, element in enumerate(seq):

··· print i, element

···

0 one

1 two

2 three

❹finditer()函数

re.finditer(pattern, string, flags = 0)

在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回

import re

it = re.finditer(r"\d+", "123abc456def789")

for match in it:

print(match.group())

输出结果:

123

456

789

❺match.group()正则表达式

我们使用group(num)或groups()匹配对象函数来获取匹配表达式

group(num = 0):匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。

groups():返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

❻正则表达式start()和end()

start([group])方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为0;

end([group])方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为0;

采用setdefault的更好的解决方法

示例 3-4 用dict.setdefault就解决了获取和更新单词的出现情况列表

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

import sys

import re

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) ➊

# 以字母顺序打印出结果

for word in sorted(index, key=str.upper):

print(word, index[word])

➊获取单词的出现情况列表,如果单词不存在,把单词和一个空列表放进映射,然后返回这个空列表,这样就能在不进行第二次查找的情况下更新列表了

也就是说,这样写

my_dict.setdefault(key, []).append(new_value)

与这样写

if key not in my_dict:

my_dict[key] = []

my_dict[key].append(new_value)

二者的效果是一样的,只不过后者至少要进行两次键查询——如果键不存在的话,就是三次,用setdefault只需要一次就可以完成整个操作。

(转载自https://blog.csdn.net/qq_43168521/article/details/103027871)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值