Python基础之yield,匿名函数,包与re模块
一.表达式形式的yield
1.另外一种形式的yield
1 def deco(func): 2 def wrapper(*arges, **kwargs): 3 res = func(*arges, **kwargs) 4 next(res) 5 return res 6 return wrapper 7 8 @deco 9 def eater(name): 10 print("%s ready to eat" % name) 11 food_list = [] 12 while True: 13 food = yield food_list 14 food_list.append(food) 15 print("%s start to eat %s" % (name, food)) 16 g = eater("alex") 17 g.send("手指头") 18 g.send("脚趾头") 19 g.send("别人的手指头") 20 g.send("别人的脚趾头") 21 """ 22 输出结果: 23 alex ready to eat 24 alex start to eat 手指头 25 alex start to eat 脚趾头 26 alex start to eat 别人的手指头 27 alex start to eat 别人的脚趾头 28 """
1 def deco(func): 2 def wrapper(*arges, **kwargs): 3 res = func(*arges, **kwargs) 4 next(res) 5 return res 6 return wrapper 7 8 @deco 9 def eater(name): 10 print("%s ready to eat" % name) 11 food_list = [] 12 while True: 13 food = yield food_list 14 food_list.append(food) 15 print("%s start to eat %s" % (name, food)) 16 g = eater("alex") 17 g.send("手指头") 18 g.send("脚趾头") 19 g.send("别人的手指头") 20 g.send("别人的脚趾头") 21 """ 22 输出结果: 23 alex ready to eat 24 alex start to eat 手指头 25 alex start to eat 脚趾头 26 alex start to eat 别人的手指头 27 alex start to eat 别人的脚趾头 28
2.表达式形式的yield
1 # -*- coding:utf-8 -*- 2 # /user/bin/python 3 import os 4 def init(func): 5 def wrapper(*args,**kwargs): 6 res=func(*args,**kwargs) 7 next(res) 8 return res 9 return wrapper 10 11 @init # 装饰器:初始化函数 12 def search(target): 13 while True: 14 search_path=yield 15 g=os.walk(search_path) # 遍历目录 16 for par_dir,_,files in g: # 用_丢弃子目录 17 for file in files: 18 file_abs_path=r'%s\%s' %(par_dir,file) # 拼接文件路径file_abs_path 19 # print(file_abs_path) 20 target.send(file_abs_path) # 遍历文件路径并send给opener函数 21 22 @init 23 def opener(target): 24 while True: 25 file_abs_path=yield 26 # print('opener func==>',file_abs_path) 27 with open(file_abs_path,encoding='utf-8') as f: 28 target.send((file_abs_path,f)) # send文件路径及文件对象f,以元组的形式send数据 29 30 @init 31 def cat(target): # target为grep函数对象 32 while True: 33 file_abs_path,f=yield #(file_abs_path,f) 34 for line in f: 35 tag=target.send((file_abs_path,line)) # send文件路径及文件行内容line,以元组的形式send数据 36 if tag: 37 break 38 @init 39 def grep(target,pattern): # target为printer函数对象,pattern为匹配的字符串'python' 40 tag=False 41 while True: 42 file_abs_path,line=yield tag 43 tag=False 44 if pattern in line: 45 tag=True 46 target.send(file_abs_path) 47 48 @init 49 def printer(): # 输出匹配成功的文件路径 50 while True: 51 file_abs_path=yield 52 print(file_abs_path) 53 54 55 56 x=r'E:\YQLFC\study\day05\day5\a' # 查找的目录 57 58 g=search(opener(cat(grep(printer(),'python')))) 59 print(g) 60 61 ''' 62 #结果 63 <generator object search at 0x0000000000D514C0> 64 E:\YQLFC\study\day05\day5\a\a.txt 65 E:\YQLFC\study\day05\day5\a\b\b.txt 66 E:\YQLFC\study\day05\day5\a\b\c\d\d.txt 67 '''
二.匿名函数lambda
1.匿名函数
1 f=lambda x,y:x+y # :...=return 2 print(f(1,2))
2.zip拉链函数,将keys与values转换
1 salaries = { 2 'json':2000, 3 'alex':100000, 4 'nickle':10000, 5 'egon': 3000 6 } 7 res= zip(salaries.values(),salaries.keys()) 8 print(list(res)) 9 """ 10 [(3000, 'egon'), (100000, 'alex'), (10000, 'nickle'), (2000, 'json')] 11 """
3.max,sorted与min函数
1 salaries = { 2 'json':2000, 3 'alex':100000, 4 'nickle':10000, 5 'egon': 3000 6 } 7 print(max(salaries, key=lambda k:salaries[k])) 8 print(min(salaries, key=lambda k:salaries[k])) 9 print(sorted(salaries,key=lambda k:salaries[k])) # 默认排序从小到大 10 """ 11 alex 12 json 13 ['json', 'egon', 'nickle', 'alex'] 14 """
三.内置函数(续)
1.global改变局部变量为全局变量
1 x = 10000 2 def func(): 3 global x 4 x = 1 5 func() 6 print(x) 7 """ 8 1 9 """
2.map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回
1 lis = ["json", "alex","nickle"] 2 res = map(lambda x:x+'_sb',lis) 3 print(list(res)) 4 """ 5 ['json_sb', 'alex_sb', 'nickle_sb'] 6 """
1 numbers = [1,2,3,4,5,3] 2 res = map(lambda x:x**2,numbers) 3 print(list(res)) 4 """ 5 [1, 4, 9, 16, 25, 9] 6 """
3.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。
1 from functools import reduce 2 numbers = [1,2,3,4,5,6] 3 res = reduce(lambda x,y:x+y,numbers,20) # 为初始值将计算结果再与20相加 4 print(res) 5 """ 6 41 7 """
4.filter()函数包括两个参数,分别是function和list。该函数根据function参数返回的结果是否为真来过滤list参数中的项,最后返回一个新列表。
1 lis = ['json_sb', 'alex_sb', 'nickle_sb',"lyl"] 2 res = filter(lambda x:x.endswith("sb"),lis) 3 print(list(res)) 4 """ 5 ['json_sb', 'alex_sb', 'nickle_sb'] 6 """
四.递归与二分法
1.递归定义,直接或间接地调用了函数本身
1 def fact(n): 2 if n==1: 3 return 1 4 return n * fact(n - 1) 5 print(fact(7)) 6 """ 7 5040 8 """
1 def age(n): 2 if n == 1: 3 return 18 4 return age(n-1)+2 5 print(age(3)) 6 """ 7 22 8 """
2.通过sys模块可以指定递归次数,默认为1000次
1 import sys 2 print(sys.getrecursionlimit()) 3 """ 4 1000 5 """
1 import sys 2 print(sys.setrecursionlimit(100000)) 3 print(sys.getrecursionlimit()) 4 """ 5 None 6 100000 7 """
3.二分法
1 l = [1, 2, 10,33,53,71,73,75,77,85,101,201,202,999,11111] 2 3 def search(find_num,seq): 4 if len(seq) == 0: 5 print('not exists') 6 return 7 mid_index=len(seq)//2 8 mid_num=seq[mid_index] 9 print(seq,mid_num) 10 if find_num > mid_num: 11 #in the right 12 seq=seq[mid_index+1:] 13 search(find_num,seq) 14 elif find_num < mid_num: 15 #in the left 16 seq=seq[:mid_index] 17 search(find_num,seq) 18 else: 19 print('find it') 20 search(1,l) 21 """ 22 [1, 2, 10, 33, 53, 71, 73, 75, 77, 85, 101, 201, 202, 999, 11111] 75 23 [1, 2, 10, 33, 53, 71, 73] 33 24 [1, 2, 10] 2 25 [1] 1 26 find it 27 """
五.正则表达式re
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换.
1.re导入模块
import re
2.正则表达式匹配规则(引于菜鸟教程)
1).正则表达式修饰符--可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
2).正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'/t',等价于'//t')匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{ n} | |
re{ n,} | 精确匹配n个前面表达式。 |
re{ n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
(re) | G匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) | 类似 (...), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#...) | 注释. |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) | 匹配的独立模式,省去回溯。 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
\1...\9 | 匹配第n个分组的内容。 |
\10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
c.正则表达式实例
字符匹配
实例 | 描述 |
---|---|
python | 匹配 "python". |
字符类
实例 | 描述 |
---|---|
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
特殊字符类
实例 | 描述 |
---|---|
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 |
\W | 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 |
3.具体方法
1).re.match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None。
re.match(pattern, string, flags=0)
- pattern表示匹配的正则表达式
- string表示要匹配的字符串
- 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
实例1
import re print(re.match("www","www.baidu.com").span()) # 在起始位置匹配 print(re.match("com","www.baidu.com")) # 不在起始位置匹配 """ (0, 3) None """
实例2
import re res = re.match('\d+', '123uuasf') if res: print (res.group()) else: print(None) """ 123 """
2).re.search方法
re.search 扫描整个字符串并返回第一个成功的匹配。函数语法同re.match方法
案例1
print(re.search('www', 'www.yaomr.com').span()) # 在起始位置匹配 print(re.search('yao', 'www.yaomr.com').span()) # 不在起始位置匹配 """ (0, 3) (4, 7) """
3).re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
实例
import re line = "Cats are smarter than dogs"; matchObj = re.match(r'dogs', line, re.M | re.I) if matchObj: print("match --> matchObj.group() : ", matchObj.group()) else: print("No match!!") matchObj = re.search(r'dogs', line, re.M | re.I) if matchObj: print("search --> matchObj.group() : ", matchObj.group()) else: print("No match!!")
4.搜索string,以列表形式返回全部能匹配的子串
语法:
re.sub(pattern, repl, string, count=0)
- pattern,正则表达式中的字符串
- repl,替换中的字符串也可能是一个函数
- string,要被查找中的原始字符串
- count,模式匹配后替换的最大次数,默认0表示替换的所有匹配
import re phone = "2004-959-559 # 这是一个电话号码" # 删除注释 num = re.sub(r'#.*$', "", phone) print ("电话号码 : ", num) # 移除非数字的内容 num = re.sub(r'\D', "", phone) print ("电话号码 : ", num) """ 电话号码 : 2004-959-559 电话号码 : 2004959559 """