难度:*
Don’t bury your burden in saintly silence. You have a problem?

page 41

如有涉及到**知识版权,联系删除

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB',
'ZB', 'YB'],1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB',
'EiB', 'ZiB', 'YiB']}
def approximate_size(size,
a_kilobyte_is_1024_bytes=True): # 1'''Convert a file size to human‐readable form.Keyword arguments:size ‐‐ file size in bytesa_kilobyte_is_1024_bytes ‐‐ if True (default), use
multiples of 1024|            if False, use multiples
of 1000Returns: string'''if size < 0:raise ValueError('number must be non‐negative') #2multiple = 1024 if a_kilobyte_is_1024_bytes else 1000 #3for suffix in SUFFIXES[multiple]:size /= multiple # 4if size < multiple:return '{0:.1f} {1}'.format(size, suffix)raise ValueError('number too large')
if __name__ == '__main__':print(approximate_size(1000000000000, False))print(approximate_size(1000000000000))
# 错误操作
# print(approximate_size(size=1000000000000,False))
# # print(approximate_size(size=1000000000000,False))
1.0 TB
931.3 GiB

学习之处:

1、设置可选参数并赋默认值,并可有他来进行判断,
2、学习通过手动判断input值来引发报错
3、学习 (#3)这种简并是写法
4、不只加减法则能这样写

again

print('{0:.1f} {1}'.format(9.333, "kb"))
print('%.1f Kb' % 9.333,)
print(f'{9.333:.1f} kb')
9.3 kb
9.3 Kb
9.3 kb
print(in)
import sys
sys.path
['/mnt/d/01Apy_study/06_reading_notes','/usr/lib/python38.zip','/usr/lib/python3.8','/usr/lib/python3.8/lib-dynload','','/home/lzy/.local/lib/python3.8/site-packages','/usr/local/lib/python3.8/dist-packages','/usr/lib/python3/dist-packages','/home/lzy/.local/lib/python3.8/site-packages/IPython/extensions','/home/lzy/.ipython']

# 将一个py导入到sys路径中
# >>> import sys
# >>> sys.path
# >>> sys.path.insert(0,'/home/lzy/01Apy_study/06_reading_notes')
# >>> sys.path
# >>> import humansize

内置数据类型

isinstance(1, int)
True
type(2.0)
float
11/2
5.5
# 分数
import fractions
x = fractions.Fraction(1, 3)  #(分子, 分母)
x*2
Fraction(2, 3)
# 三角函数
import math
print(math.pi)
print(math.sin(math.pi / 2))
3.141592653589793
1.0

略列表、创建列表、列表切片、

a_list=['a', 'b', 'mpilgrim', 'z', 'example']
print(a_list[1:-1])
print(a_list[1::-1])
print(a_list[1:1])
print(a_list[::-1])
print(a_list+[2.0,3])
# 理解
# a_list.append()
# a_list.extend()
a_list.insert(0, 'Ω')
a_list
['b', 'mpilgrim', 'z']
['b', 'a']
[]
['example', 'z', 'mpilgrim', 'b', 'a']
['a', 'b', 'mpilgrim', 'z', 'example', 2.0, 3]['Ω', 'a', 'b', 'mpilgrim', 'z', 'example']

在列表中检索值

a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
print(a_list.count('new'))
print('new' in a_list)
print(a_list.index('mpilgrim'))
2
True
3

从列表中删除元素

a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
del a_list[1]
a_list
['a', 'new', 'mpilgrim', 'new']
a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
a_list.remove('new')
print(a_list)
a_list.remove('new')
print(a_list)
['a', 'b', 'mpilgrim', 'new']
['a', 'b', 'mpilgrim']
a_list = ['a', 'b', 'new', 'mpilgrim']
print(a_list.pop())
print(a_list)
a_list.pop(1)
mpilgrim
['a', 'b', 'new']'b'

略 布尔上下文环境中的列表、元组、

同时赋多个值

v = ('a', 2, True)
(x, y, z) = v
print(x,y,z)
(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, SUNDAY) = range(7)
print(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, SUNDAY)
a 2 True
0 1 2 3 4 5 6

集合

a_set = {1, 2}
a_set.add(4)
print(a_set)
a_set.update({2, 4, 6})
print(a_set)
a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})
print(a_set)
a_set.update([10, 20, 30])
print(a_set)
# update() 方法仅接受一个集合作为参数,
#update() 将会把列表中所有的元素添加到初始集合中
{1, 2, 4}
{1, 2, 4, 6}
{1, 2, 3, 4, 5, 6, 8, 9, 13}
{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
# 1. discard() 接受一个单值作为参数,并从集合中删除该值。
# 2. 如果针对一个集合中不存在的值调用 discard() 方法,它不
# 进行任何操作。不产生错误;只是一条空指令。
# 3. remove() 方法也接受一个单值作为参数,也从集合中将其删
# 除。
# 4. 区别在这里:如果该值不在集合中,remove() 方法引发一个
# KeyError 例外。
## 集合是无序的,所以用pop() 删除的时候是随机的

常见集合操作

a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
print(30 in a_set )
b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
print(a_set.union(b_set))
print(a_set.intersection(b_set))
print(a_set.difference(b_set))
print(a_set.symmetric_difference(b_set))
True
{1, 2, 195, 4, 5, 3, 6, 8, 9, 12, 76, 15, 17, 18, 21, 30, 51, 127}
{2, 5, 9, 12, 21}
{195, 4, 76, 51, 30, 127}
{1, 3, 195, 6, 4, 8, 76, 15, 17, 18, 51, 30, 127}
# 1. 要检测某值是否是集合的成员,可使用 in 运算符。其工作原
# 理和列表的一样。
# 2. union() 方法返回一个新集合,其中装着 在两个 集合中出现
# 的元素。
# 3. intersection() 方法返回一个新集合,其中装着 同时 在两个
# 集合中出现的所有元素。
# 4. difference() 方法返回的新集合中,装着所有在 a_set 出现
# 但未在 b_set 中的元素。
# 5. symmetric_difference() 方法返回一个新集合,其中装着所
# 有 只在其中一个 集合中出现的元素。

字典

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB','EB', 'ZB', 'YB'], 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB','EiB', 'ZiB', 'YiB']}
print(len(SUFFIXES))
print(SUFFIXES[1000][3])
2
TB

深入阅读

处理文件和目录

# Python 3 带有一个模块叫做 os,代表 “操作系统(operatingsystem)。
import os
print(os.getcwd())
os.chdir('/home/lzy/01Apy_study/')
print(os.getcwd())
os.chdir('/home/lzy/01Apy_study/06_reading_notes')
/mnt/d/01Apy_study/06_reading_notes
/mnt/d/01Apy_study
print(os.path.join('/home/lzy/01Apy_study/06_reading_notes', 'humansize.py'))
/home/lzy/01Apy_study/06_reading_notes/humansize.py
print(os.path.expanduser('~')) # 不以斜杠结尾,但os.path.join() 并不介意这一点
print(os.path.join(os.path.expanduser('~'),
'diveintopython3', 'examples', 'humansize.py'))
/home/lzy
/home/lzy/diveintopython3/examples/humansize.py
pathname ='/Users/pilgrim/diveintopython3/examples/humansize.py'
print(os.path.split(pathname))
(dirname, filename) = os.path.split(pathname)
print(dirname, filename)
(shortname, extension) = os.path.splitext(filename)
print(shortname, extension,sep='\t')
# os.path 也包含 os.path.splitext() 函数,它分割一个文件名并返回短文件名和扩展名。
('/Users/pilgrim/diveintopython3/examples', 'humansize.py')
/Users/pilgrim/diveintopython3/examples humansize.py
humansize   .py

罗列目录内容、获取文件信息

!ls
'Dive into python.ipynb'   __pycache__  hello_world.py   humansize.py
import glob
glob.glob('./h*py')
#glob 模式中你可以使用多个通配符
['./hello_world.py', './humansize.py']
metadata = os.stat('./humansize.py')
print(metadata.st_mtime)
import time
print(time.localtime(metadata.st_mtime))
print(metadata.st_size)
import humansize
print(humansize.approximate_size(metadata.st_size))
1637898939.9567592
time.struct_time(tm_year=2021, tm_mon=11, tm_mday=26, tm_hour=11, tm_min=55, tm_sec=39, tm_wday=4, tm_yday=330, tm_isdst=0)
1058
1.0 KiB

构造绝对路径

# glob.glob() 函数返回一个相对路径的列表
# 望构造一个从根目录开始或者是包含盘符的绝对路径
# 时,你就需要用到os.path.realpath()函数了。
import os
print(os.getcwd)
print(os.path.realpath('./hello_world.py'))
<built-in function getcwd>
/mnt/d/01Apy_study/06_reading_notes/hello_world.py

列表解析

#列表解析提供了一种紧凑的方式,实现了通过对列表中每一个
# 元素应用一个函数的方法来将一个列表映射到另一个列表
a_list=[1,2,3,4]
print([tmp * 2 for tmp in a_list])
import os, glob
print(glob.glob('h*py'))
print([os.path.realpath(f) for f in glob.glob('h*py')])
## 加过滤
print([os.stat(f).st_size for f in glob.glob('*py')])
print([f for f in glob.glob('*py') if os.stat(f).st_size > 100])
[2, 4, 6, 8]
['hello_world.py', 'humansize.py']
['/mnt/d/01Apy_study/06_reading_notes/hello_world.py', '/mnt/d/01Apy_study/06_reading_notes/humansize.py']
[20, 1058]
['humansize.py']
print([(os.stat(f).st_size, os.path.realpath(f)) for f in glob.glob("*py")])
import humansize
[(humansize.approximate_size(os.stat(f).st_size), os.path.realpath(f)) for f in glob.glob("*py")]
[(20, '/mnt/d/01Apy_study/06_reading_notes/hello_world.py'), (1058, '/mnt/d/01Apy_study/06_reading_notes/humansize.py')][('0.0 KiB', '/mnt/d/01Apy_study/06_reading_notes/hello_world.py'),('1.0 KiB', '/mnt/d/01Apy_study/06_reading_notes/humansize.py')]

字典解析

# 字典解析和列表解析类似,只不过它生成字典而不是列表。
metadata_dict = {f:os.stat(f) for f in glob.glob('*h*.py')}
print(type(metadata_dict))
print(metadata_dict.keys())
print(humansize.approximate_size(metadata_dict['humansize.py'].st_size))
<class 'dict'>
dict_keys(['hello_world.py', 'humansize.py'])
1.0 KiB
import os,glob,humansize
metadata_dict={f:os.stat(f) for f in glob.glob('*py')}
print(metadata_dict.keys())
humansize_dict={os.path.splitext(f)[0]:humansize.approximate_size(meta.st_size) for f,meta in metadata_dict.items() if meta.st_size > 100}
print(humansize_dict.keys())
print(humansize_dict['humansize'])
dict_keys(['hello_world.py', 'humansize.py'])
dict_keys(['humansize'])
1.0 KiB
# 这里是一个可能有用的通过字典解析实现的小技巧: 交换字典的
# 键和值。
a_dict = {'a': 1, 'b': 2, 'c': 3}
{value:key for key,value in a_dict.items()}
{1: 'a', 2: 'b', 3: 'c'}

集合解析 (略 与列表相似)

难度: ***

字符串

格式化字符串

username = 'mark'
password = 'PapayaWhip'
"{0}'s password is {1}".format(username,password)
#  placeholder
# {0}和{1} 叫做替换字段
"mark's password is PapayaWhip"

复合字段名

import humansize
help(humansize)
Help on module humansize:NAMEhumansizeFUNCTIONSapproximate_size(size, a_kilobyte_is_1024_bytes=True)Convert a file size to human‐readable form.Keyword arguments:size ‐‐ file size in bytesa_kilobyte_is_1024_bytes ‐‐ if True (default), usemultiples of 1024|            if False, use multiplesof 1000Returns: stringDATASUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], 10...FILE/mnt/d/01Apy_study/06_reading_notes/humansize.py
si_suffixes = humansize.SUFFIXES[1000]
print(si_suffixes)
'1000{0[0]} = 1{0[1]}'.format(si_suffixes) # 这一句看上去有些复杂,其实不是这样的。{0}代表传递给
# format()方法的第一个参数,即 si_suffixes。注意
# si_suffixes 是一个列表。所以{0[0]}指代 si_suffixes 的第一
# 个元素,即'KB'。同时,{0[1]}指代该列表的第二个元素,
# 即:'MB'。大括号以外的内容 — 包括 1000,#使用列表作为参数,并且通过下标索引来访问其元素(跟上
# 一例类似)
['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']'1000KB = 1MB'
import humansize
import sys
'1MB = 1000{0.modules[humansize].SUFFIXES[1000][0]}'.format(sys)
sys 模块保存了当前正在运行的 Python 实例的信息。由于已
经导入了这个模块,因此可以将其作为 format()方法的参数。
所以替换域{0}指代 sys 模块。 sys.modules 是一个保
存当前 Python 实例中所有已经导入模块的字典。模块的名字
作为字典的键;模块自身则是键所对应的值。所以{0.modules}
指代保存当前己被导入模块的字典。 sys.modules['humansize'].SUFFIXES 是在 humansize 模块的
开头定义的一个字典对象。 {0.modules[humansize].SUFFIXES}
即指向该字典。
'1MB = 1000KB'

格式说明符

# if size < multiple:
#     return '{0:.1f} {1}'.format(size, suffix)
# 冒号(:)标示格式说明符的开始。
'{0:.1f} {1}'.format(698.24, 'GB')
'698.2 GB'
query ='user=pilgrim&database=master&password=PapayaWhip'
a_list = query.split('&')
print(a_list)
a_list_of_lists = [v.split('=',1) for v in a_list]
print(a_list_of_lists)
a_dict= dict(a_list_of_lists)
print(a_dict)
['user=pilgrim', 'database=master', 'password=PapayaWhip']
[['user', 'pilgrim'], ['database', 'master'], ['password', 'PapayaWhip']]
{'user': 'pilgrim', 'database': 'master', 'password': 'PapayaWhip'}
[v.split('=') for v in a_list]
[['user', 'pilgrim'], ['database', 'master'], ['password', 'PapayaWhip']]
a_string = '深入Python'
print(len(a_string))
by = a_string.encode('utf‐8')
print(by)
print(len(by))
8
b'\xe6\xb7\xb1\xe5\x85\xa5Python'
12

正则表达式

# 回顾
# 替换字符串的方法是:index()、 find()、split()、 count()、replace()等。
# 用index()方法查找单个子字符串,而且查找总是区分大小写的。
# 为了使用不区分大小写的查找,可以使用 s.lower()或者s.upper(),
# 调用 split() 和 join() 来切片、合并你的字符串,

案例研究:街道地址

s = '100 NORTH MAIN ROAD'
s.replace('ROAD','RD')
'100 NORTH MAIN RD'
s = '100 NORTH BROAD ROAD'
s.replace('ROAD','RD.')
'100 NORTH BRD. RD.'
print(s[:-4] + s[-4:].replace('ROAD', 'RD.'))
import re
print(re.sub('ROAD$','RD.',s))
100 NORTH BROAD RD.
100 NORTH BROAD RD.
s = '100 BROAD'
re.sub(r'\bROAD$', 'RD.', s)
'100 BROAD'

案例研究:罗马数字

# • I = 1
# • V = 5
# • X = 10
# • L = 50
# • C = 100
# • D = 500
# • M = 1000
# (I,X,C 和 M)最多可以重复出现三个
# 罗马数字是从左到右来计算,
#  ?  匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
# 检查千位数字的罗马表示方法
pattern ='^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'

松散正则表达式

python 允许你使用松散正字表达式来达到目的。松散正字表达
式和普通紧凑的正则表达式有两点不同:
• 空白符被忽略。空格、制表符和回车在正则表达式中并不会
匹配空格、制表符、回车。如果你想在正则表达式中匹配他
们,可以在前面加一个\来转义。
• 注释信息被忽略。松散正字表达式中的注释和 python 代码中
的一样,都是以#开头直到行尾。它可以在多行正则表达式中
增加注释信息,这就避免了在 python 代码中的多行注释。他们
的工作方式是一样的。

pattern = '''^                   # beginning of stringM{0,3}              # thousands ‐ 0 to 3 Ms(CM|CD|D?C{0,3})    # hundreds ‐ 900 (CM), 400 (CD),0‐300 (0 to 3 Cs),#            or 500‐800 (D,followed by 0 to 3 Cs)(XC|XL|L?X{0,3})    # tens ‐ 90 (XC), 40 (XL), 0‐30(0 to 3 Xs),#        or 50‐80 (L, followed by 0 to 3 Xs)(IX|IV|V?I{0,3})    # ones ‐ 9 (IX), 4 (IV), 0‐3 (0 to 3 Is),#        or 5‐8 (V, followed by 0 to 3 Is)$                   # end of string'''
re.search(pattern, 'MMMDCCCLXXXVIII', re.VERBOSE)  # re.VERBOSE  松散正则的表示
<re.Match object; span=(0, 15), match='MMMDCCCLXXXVIII'>
  1. 注意,如果要使用松散正则表达式,需要传递一个叫
    re.VERBOSE 的参数。就像你看到的那样,正则表达式中有很多
    空白符,他们都被忽略掉了。

案例研究:解析电话号码

\d 匹配所有 0‐9 的数字. \D 匹配除了数字外的所有字符.

正则表达式规则:https://www.runoob.com/python/python-reg-expressions.html

phonePattern = re.compile(r'^(\d{3})‐(\d{3})‐(\d{4})$')
phonePattern.search('800‐555‐1212').groups()
# 了解r和\的作用
# 为了使用正则表达式匹配到的这些分组,需要对 search()函数的返回值调用 groups()方法。
('800', '555', '1212')
phonePattern = re.compile(r'(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')
phonePattern.search('work 1‐(800) 555.1212#1234').groups()
('800', '555', '1212', '1234')
# 改为松散正则表达式
phonePattern = re.compile(r'''# don't match beginning of string, number can start anywhere(\d{3})     # area code is 3 digits (e.g. '800')\D*         # optional separator is any number of non‐digits(\d{3})     # trunk is 3 digits (e.g. '555')\D*         # optional separator(\d{4})     # rest of number is 4 digits (e.g. '1212')\D*         # optional separator(\d*)       # extension is optional and can be any number of digits$           # end of string''', re.VERBOSE)
phonePattern.search('work 1‐(800) 555.1212#1234').groups()
('800', '555', '1212', '1234')

小结

现在,你应该已经熟悉了下面的技巧:

• ^ 匹配字符串开始位置。
• $ 匹配字符串结束位置。
• \b 匹配一个单词边界。
• \d 匹配一个数字。
• \D 匹配一个任意的非数字字符。
• x? 匹配可选的 x 字符。换句话说,就是 0 个或者 1 个 x 字
符。
• x* 匹配 0 个或更多的 x。
• x+ 匹配 1 个或者更多 x。
• x{n,m} 匹配 n 到 m 个 x,至少 n 个,不能超过 m 个。
• (a|b|c) 匹配单独的任意一个 a 或者 b 或者 c。
• (x) 这是一个组,它会记忆它匹配到的字符串。你可以用
re.search 返回的匹配对象的 groups()函数来获取到匹配的值。
正则表达式非常强大,但它也并不是解决每一个问题的正确答
案。你需要更多的了解来判断哪些情况适合使用正则表达式。
某些时候它可以解决你的问题,某些时候它可能带来更多的问
题。

re.match函数:

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none。

re.search方法

re.search 扫描整个字符串并返回第一个成功的匹配。

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

检索和替换

Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。

re.sub(pattern, repl, string, count=0, flags=0)

pattern: 要替换内容的正则表达

repl:要用来替换的字符,可以是一个函数

findall:
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

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

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

import re# 将匹配的数字乘以 2
def double(matched):value = int(matched.group('value'))return str(value * 2)s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
A46G8HFD1134

难度:**

闭合与生成器

❝ My spelling is Wobbly. It’s good spelling but it Wobbles, and the
letters get in the wrong places.❞

— Winnie‐the‐Pooh

• 如果某个单词以 S 、X 或 Z 结尾,添加 ES 。Bass 变成
basses, fax 变成 faxes,而 waltz 变成 waltzes。
• 如果某个单词以发音的 H 结尾,加 ES;如果以不发音的 H 结
尾,只需加上 S 。什么是发音的 H ?指的是它和其它字母组合
在一起发出能够听到的声音。因此 coach 变成 coaches 而 rash 变
成 rashes,因为在说这两个单词的时候,能够听到 CH 和 SH 的
发音。但是 cheetah 变成 cheetahs,因为 H 不发音。
• 如果某个单词以发 I 音的字母 Y 结尾,将 Y 改成 IES;如果 Y
与某个原因字母组合发其它音的话,只需加上 S 。因此 vacancy
变成 vacancies,但 day 变成 days 。
• 如果所有这些规则都不适用,只需加上 S 并作最好的打算。
(我知道,还有许多例外情况。Man 变成 men 而 woman 变成
women,但是 human 变成 humans。Mouse 变成 mice ; louse 变
成 lice,但 house 变成 houses。Knife 变成 knives ;wife 变成
wives,但是 lowlife 变成 lowlifes。而且甚至我还没有开始提到那
些原型和复数形式相同的单词,就像 sheep、 deer 和 haiku。)

import re
def plural(noun):if re.search('[sxz]$',noun):return re.sub('$','es',noun)elif re.search('[^aeioudgkprt]h$', noun):return re.sub('$', 'es', noun)        elif re.search('[^aeiou]y$', noun):       return re.sub('y$', 'ies', noun)      else:return noun + 's'
plural('vacancy')
'vacancies'

函数列表

现在要增加一些抽象层次的内容。我们开始时定义了一系列规
则:

如果这样,那样做;否则前往下一条规则。

现在让我们对
部分程序进行临时的复杂化,以简化另一部分。

# plural2.py
import re
def match_sxz(noun):return re.search('[sxz]$', noun)
def apply_sxz(noun):return re.sub('$', 'es', noun)
def match_h(noun):return re.search('[^aeioudgkprt]h$', noun)
def apply_h(noun):return re.sub('$', 'es', noun)
def match_y(noun):                             return re.search('[^aeiou]y$', noun)
def apply_y(noun):                             return re.sub('y$', 'ies', noun)
def match_default(noun):return True
def apply_default(noun):return noun + 's'
rules = ((match_sxz, apply_sxz),               (match_h, apply_h),(match_y, apply_y),(match_default, apply_default))
def plural(noun):            for matches_rule, apply_rule in rules:       if matches_rule(noun):return apply_rule(noun)
plural('vacancy')
'vacancies'

匹配模式列表

其实并不是真的有必要为每个匹配和应用规则定义各自的命名
函数。它们从未直接被调用,而只是被添加到 rules 序列并从
该处被调用。此外,每个函数遵循两种模式的其中之一。所有
的匹配函数调用 re.search(),而所有的应用函数调用
re.sub()。让我们将模式排除在考虑因素之外,使新规则定义
更加简单。

# plural3.py
import re
def build_match_and_apply_functions(pattern, search,replace):def matches_rule(word):return re.search(pattern, word)def apply_rule(word):return re.sub(search, replace, word)return (matches_rule, apply_rule)
patterns =(('[sxz]$',           '$',  'es'),('[^aeioudgkprt]h$', '$',  'es'),('(qu|[^aeiou])y$',  'y$', 'ies'),('$',                '$',  's')   )
rules = [build_match_and_apply_functions(pattern, search,replace)for (pattern, search, replace) in patterns]
def plural(noun):for matches_rule, apply_rule in rules:if matches_rule(noun):return apply_rule(noun)

匹配模式文件

目前,已经排除了重复代码,增加了足够的抽象性,因此复数
形式规则可以字符串列表的形式进行定义。下一个逻辑步骤是
将这些字符串放入一个单独的文件中,因此可独立于使用它们
的代码来进行维护。
首先,让我们创建一份包含所需规则的文本文件。没有花哨的
数据结构,只有空白符分隔的三列字符串。将其命名为
plural4‐rules.txt.

# [download plural4‐rules.txt]
# [sxz]$               $    es
# [^aeioudgkprt]h$     $    es
# [^aeiou]y$          y$    ies
# $                    $    s
import re
def build_match_and_apply_functions(pattern, search,replace):def matches_rule(word):return re.search(pattern, word)def apply_rule(word):return re.sub(search, replace, word)return (matches_rule, apply_rule)
rules = []
with open('./plural4-rules.txt', encoding='utf‐8') as pattern_file:for line in pattern_file:pattern, search, replace = line.split()  # 以空格为分隔符,包含 \n
rules.append(build_match_and_apply_functions(pattern, search, replace))
#build_match_and_apply_functions() 函数没有发生变化。仍
# 然使用了闭合技术:通过外部函数中定义的变量来动态创建两
# 个函数。

以上复数形式规则好处:

此处的改进是将复数形式规则独立地放到了一份外部文件中,
因此可独立于使用它的代码单独对规则进行维护。代码是代
码,数据是数据,生活更美好。

生成器

#plural5.py
def rules(rules_filename):with open(rules_filename, encoding='utf‐8') as pattern_file:for line in pattern_file:pattern, search, replace = line.split(None,3)yield
build_match_and_apply_functions(pattern, search, replace)
def plural(noun, rules_filename='plural5‐rules.txt'):for matches_rule, apply_rule in rules(rules_filename):if matches_rule(noun):return apply_rule(noun)raise ValueError('no matching rule for {0}'.format(noun))

为了解以上代码运行,我们先看一个交互式例子

def make_counter(x):print('entering make_counter')while True:yield xprint('incrementing x')x = x+1
couter = make_counter(2)
print(couter)
print('.............')
print(next(couter))
print(next(couter))
print(next(couter))
<generator object make_counter at 0x7f1030642900>
.............
entering make_counter
2
incrementing x
3
incrementing x
4
  1. make_counter 中出现的 yield 命令的意思是这不是一个普通
    的函数。它是一次生成一个值的特殊类型函数。可以将其视为
    可恢复函数。调用该函数将返回一个可用于生成连续 x 值的 生
    成器【Generator】。
  2. 为创建 make_counter 生成器的实例,仅需像调用其它函数那
    样对它进行调用。注意该调用并不实际执行函数代码。可以这
    么说,是因为 make_counter() 函数的第一行调用了 print(),
    但实际并未打印任何内容。
  3. 该 make_counter() 函数返回了一个生成器对象。
  4. next() 函数以一个生成器对象为参数,并返回其下一个值。
    对 counter 生成器第一次调用 next() ,它针对第一条 yield 语
    句执行 make_counter() 中的代码,然后返回所产生的值。在此
    情况下,该代码输出将为 2,因其仅通过调用 make_counter(2)
    对生成器进行初始创建。
  5. 对同一生成器对象反复调用 next() 将确切地从上次调用的位
    置开始继续,直到下一条 yield 语句。所有的变量、局部数据
    等内容在 yield 时被保存,在 next() 时被恢复。下一行代码等
    待被执行以调用 print() 以打印出 incrementing x 。之后,执
    行语句 x = x + 1。然后它继续通过 while 再次循环,而它再次
    遇上的第一条语句是 yield x,该语句将保存所有一切状态,并
    返回当前 x 的值(当前为 3)。
  6. 第二次调用 next(counter) 时,又进行了同样的工作,但这
    次 x 为 4。
    由于 make_counter 设置了一个无限循环,理论上可以永远执行
    该过程,它将不断递增 x 并输出数值。还是让我们看一个更加
    实用的生成器用法。

斐波那奇生成器

“yield” 暂停一个函数。“next()” 从其暂停处恢复其运行。

#  fibonacci.py
def fib(max):a, b = 0, 1          while a < max:yield a          a, b = b, a + b
from fibonacci import fib
for n in fib(1000):print(n,end=' ')
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

复数规则生成器

# plural5.py
def rules(rules_filename):with open(rules_filename, encoding='utf‐8') as pattern_file:for line in pattern_file:pattern, search, replace = line.split() yield
build_match_and_apply_functions(pattern, search, replace)
def plural(noun, rules_filename='plural5-rules.txt'):for matches_rule, apply_rule in rules(rules_filename):if matches_rule(noun):return apply_rule(noun)raise ValueError('no matching rule for {0}'.format(noun))
# for line in open('./plural5-rules.txt','r'):
#     pattern, search, replace = line.split()
#     print(pattern, search, replace)
# plural('vocanny')

难度:***

类&迭代器

生成器是一类特殊 迭代器。 一个产生值的函数 yield 是一种产
生一个迭代器却不需要构建迭代器的精密小巧的方法。 我会告
诉你我是什么意思。

# fibonacci2.py
class Fib: # 没有从其他类继承。 类名通常是大写字 (非必须)'''生成斐波拉稀数列的迭代器''' # 类同样可以 (而且应该) 具有 docstring, 与模块和方法一样。  def __init__(self,max):  #每个方法的第一个参数,包括 __init__() 方法,永远指向当前的类对象。 习惯上,该参数叫 self。self.max = max #self.max 是什么? 它就是实例变量。def __iter__(self):self.a=0self.b = 1return selfdef __next__(self):fib = self.aif fib > self.max:raise StopIterationself.a, self.b, self.a + self.breturn fib

类的定义

Python 是完全面向对象的:你可以定义自己的类,从你自己或
系统自带的类继承,并生成实例。
在 Python 里定义一个类非常简单。就像函数一样, 没有分开
的接口定义。 只需定义类就开始编码。 Python 类以保留字
class 开始, 后面跟类名。 技术上来说,只需要这么多就够
了,因为一个类不是必须继承其他类。

实例化类

Python 中实例化类很直接。 实例化类时就像调用函数一样简
单,将 init() 方法需要的参数传入。 返回值就是新创建的
对象。

import fibonacci2
fib = fibonacci2.Fib(100) #创建一个 Fib 类的实例(在 fibonacci2 模块中定义) 将
#                             新创建的实例赋给变量 fib。 你传入一个参数 100, 这是 Fib
#                             的__init__()方法作为 max 参数传入的结束值。
print(fib)
print(fib.__class__ )
print(fib.__doc__)
<fibonacci2.Fib object at 0x7f1030c0e250>
<class 'fibonacci2.Fib'>
生成斐波拉稀数列的迭代器

实例变量

import fibonacci2
fib1 = fibonacci2.Fib(100)
fib2 = fibonacci2.Fib(200)
print(fib1.max)
print(fib2.max)
!cat fibonacci2.py
class Fib: # 没有从其他类继承。 类名通常是大写字 (非必须)'''生成斐波拉稀数列的迭代器''' # 类同样可以 (而且应该) 具有 docstring, 与模块和方法一样。  def __init__(self,max):  #每个方法的第一个参数,包括 __init__() 方法,永远指向当前的类对象。 习惯上,该参数叫 self。self.max = maxdef __iter__(self):self.a=0self.b = 1return selfdef __next__(self):fib = self.aif fib > self.max:raise StopIterationself.a, self.b, self.a + self.breturn fib

菲波拉稀迭代器

创建一个迭代器了。 迭代器就是一个
定义了 iter() 方法的类。 这些类的所有三种方法,
inititer, 和 next, 起始和结束均为一对下划
线(_) 字符。 为什么这样? 并无什么神奇之处, 只是通常表
示这是“特殊方法。” 唯一“特殊”的地方,就是这些方法不是直
接调用的; 当你使用类或实例的某些语法时,Python会自动调
用他们。

# fibonacci2.py
class Fib: # 没有从其他类继承。 类名通常是大写字 (非必须)'''生成斐波拉稀数列的迭代器''' # 类同样可以 (而且应该) 具有 docstring, 与模块和方法一样。  def __init__(self,max):  #每个方法的第一个参数,包括 __init__() 方法,永远指向当前的类对象。 习惯上,该参数叫 self。self.max = max #self.max 是什么? 它就是实例变量。保存最大值,以便随后的其他方法可以引用。  def __iter__(self): # 调用 iter(fib)的时候,__iter__()就会被调用。self.a=0self.b = 1return selfdef __next__(self):#调用 next()方法时,__next__() 会自动调用。fib = self.aif fib > self.max:raise StopIterationself.a, self.b, self.a + self.breturn fib
# for n in Fib(1000):
#      print(n, end=' ')
!cat fibonacci2.py
class Fib:'''生成菲波拉稀数列的迭代器'''def __init__(self, max):self.max = maxdef __iter__(self):self.a = 0self.b = 1return selfdef __next__(self):fib = self.aif fib > self.max:raise StopIterationself.a, self.b = self.b, self.a + self.breturn fib

暂时看到 page:205,因为后面涉及的东西超过认知了,后面再看(以后更新)









01_Dive_into_python (reading note)相关推荐

  1. GAN-overview reading note(3)Wasserstein GAN

    文章目录 了解WGAN 强行写点理解 2019.4.13--子涣 了解WGAN 继续读GAN overview,在第一部分基本了解了GAN的基本概念,又在第二部分了解了LSGAN对其的改进,同时也基本 ...

  2. idea两个好用的插件-Code Reading Note与RestfulTool

    1.问题描述 介绍两个idea插件,感觉很好用,记录下. 2.问题描述解决 2.1 Code Reading Note插件--代码阅读笔记 这个插件的原始功能是:对指定代码记录阅读笔记,然后增加到指定 ...

  3. Reading Note(8) ——GNN for DSE Optimization

    这篇博客是一篇论文阅读札记,这篇论文的主题是使用GNN来优化加速器设计中的设计空间探索耗时过长的问题. 这篇文章的标题是<Enabling Automated FPGA Accelerator ...

  4. 「MICCAI 2016」Reading Note

    Sina Weibo:东莞小锋子Sexyphone Tencent E-mail:403568338@qq.com http://blog.csdn.net/dgyuanshaofeng/articl ...

  5. READING NOTE: R-FCN: Object Detection via Region-based Fully Convolutional Networks

    转载自: http://blog.csdn.net/joshua_1988/article/details/51484412 TITLE: R-FCN: Object Detection via Re ...

  6. Thinking in Java Reading Note(5.初始化与清理)

    1.用构造器确保初始化 可以假想为编写的每个类都定义一个initialize()方法.该方法的名称提醒你在使用其对象之前,应首先调用initialize().然而,这同时意味着用户必须记得自己去调用此 ...

  7. CoreJava Reading Note(3:Fundamental structure)

    1.CamelCase 类名是以大写字母开头的词,如果名字由多个单词组成,每个单词的地一个字母都应该大写. 例如:FirstExample,ObjectDemo..... 2.数据类型 a.整型: i ...

  8. Reading Note(10)——AutoBridge

    这篇论文是FPGA 2021年的best paper award,主要解决的是在HLS编译过程中优化布局和布线,最终达到整个multi-die的FPGA板上的大规模HLS设计时钟频率尽可能提升的目的, ...

  9. Paper Reading: Generating Artistic Portrait Drawings from Face Photos with Hierarchical GANs

    Paper Reading Note URL: https://cg.cs.tsinghua.edu.cn/papers/CVPR-2019-Drawing.pdf TL;DR CVPR2019一篇来 ...

最新文章

  1. 分布式系统的复杂度度量思考
  2. html酒鬼酒网站制作,酒鬼酒
  3. DS-1 数据结构和算法刷题
  4. golang中的栈帧
  5. XCode中安装cocoapods步骤
  6. 到2020年,将有60%的工作被人工智能取代?
  7. Notepad++ 添加Json格式化插件
  8. 从零写一个编译器(四):语法分析之构造有限状态自动机
  9. 《编程之美》读书笔记(十二):“只考加法的面试题”
  10. JAVA出现空指针异常(初学者)
  11. Vue或React多页应用脚手架
  12. 开发了一套python的七牛sdk
  13. Google 纪念万维网 30 年:没有 HTTP 协议就没有互联网
  14. 第二届上汽零束SOA平台开发者大会揭幕,智能汽车生态加速落地
  15. 笔记本实现有线路由器功能
  16. MySQL 怎么插入10天前的日期_使用 MySQL 的 SQL_MODE 有哪些坑,你知道么?
  17. 起点:如何成为一名黑客?
  18. echarts 渲染3d地图
  19. 工具包-POST请求
  20. 纯日记+游戏推荐(妈妈把我的游戏藏起来了)

热门文章

  1. [Copy] Netlink Socket
  2. bbs.php ww1.dzxa.me_bbs论坛小结
  3. Hive数据去重、多变一与一变多等实现
  4. Python刷题中常用的知识点和易忘点
  5. 零基础教你Unity制作像素鸟游戏 【文末源码】
  6. ​浙江省交通运输物流信息服务中心平台容灾设备采购二期项目
  7. Unity 两张Texture叠加时用到的颜色混合
  8. 23届应届毕业生秋招分享——秋招经验
  9. 宽依赖和窄依赖_Spark --【宽依赖和窄依赖】
  10. 分析:日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯 的一个。以下为4个嫌疑犯的供词, 问题