1.介绍
- 正则表达式
- 装饰器
- 迭代器
- 生成器
- 多任务
2.实践
2.1 正则表达式
用re模块检查一个字符串是否与某种模式匹配
-
^ 表示匹配字符串的开始位置 $ 表示匹配字符串的结束位置
-
匹配一个长度为0的子串
-
s 匹配空白字符,比如空格,换行等
-
大小写快速取反
- w 表示匹配英文字母和数字W 匹配非英文字母和数字
- d 匹配数字 D 匹配非数字
-
.表示匹配单个字符
-
|表示为或者,两项中取一项 a|b 匹配a或者b
-
( ) 小括号表示匹配括号中全部字符 (abc) 匹配abc
-
[] 中括号表示匹配括号中一个字符 [0-9 a-z A-Z]
-
重复匹配
- {n}表示匹配n个字符
- {n,}表示至少匹配n个字符
- {n,m}表示至少n,最多m 优先匹配N个数字(贪婪模式)
- {M,N}? 非贪婪模式,只匹配M个数字
- *表示匹配0到多次
- +表示匹配1次到多次
- ? 表示匹配0或1
-
标记
- re.I 使匹配不区分大小写
- re.M (re.MULTILINE)多行匹配,影响 ^ 和 $
- re.S (re.DOTALL)使 . 匹配包括换行在内的所有字符
- re.U 根据Unicode字符集解析字符。这个标志影响 w, W
2.1.1 re.match
re.match 尝试从字符串的起始位置匹配一个模式
import re
print(re.match('www', 'www.huawei.com')) # 默认在起始位置匹配 www
print(re.match('com', 'www.huawei.com')) # 无法匹配
print(re.match('.*com$','www.huawei.com')) # 正则表达式表示匹配末尾为.com 的对象
<re.Match object; span=(0, 3), match='www'>
None
<re.Match object; span=(0, 14), match='www.huawei.com'>
2.1.2 re.search
扫描整个字符串并返回第一个成功的匹配
import re
print(re.search('www', 'www.huawei.com')) # 搜索到开始 www
print(re.search('com', 'www.huawei.com')) # 搜到到最末 com
print(re.search('.*com$','www.huawei.com')) # 正则表达式表示匹配末尾为.com 的对象
print(re.search('COM', 'www.huawei.com',re.I)) # 使大小写不敏感
<re.Match object; span=(0, 3), match='www'>
<re.Match object; span=(11, 14), match='com'>
<re.Match object; span=(0, 14), match='www.huawei.com'>
<re.Match object; span=(11, 14), match='com'>
2.1.3 re.sub
re.sub 用于替换字符串中的匹配项re.sub(pattern, repl, string, count=0, flags=0)
搜索pattern,替换成rep1
import re
print(re.sub('^WWW','support', 'www.huawei.com',flags=re.I)) # 将开始的 www,替换为 support
support.huawei.com
2.1.4 re.compile
生成一个正则表达式(Pattern)对象,供 match() 和
search() 这两个函数使用
re.compile(pattern[, flags])
import re
pattern = re.compile('d+') #匹配至少一个数字
print (pattern.match( 'www.huawei123.com')) #查看头部是否有数字,没有匹配
print (pattern.search( 'www.huawei123.com')) #搜索返回第一个数字
None
<re.Match object; span=(10, 13), match='123'>
2.1.5 findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹
配的,则返回空列表。
findall(string[, pos[, endpos]])
- string 为待匹配字符串。
- Pos 指定字符串的起始位置,默认为 0。
- Endpos 指定字符串结束位置,默认为字符串长度
import re
pattern = re.compile('d+') #匹配至少一个数字
print(pattern.findall( 'www.huawei123.com
345')) #查找所有字符串
['123', '345']
2.1.6 re.split()
split 按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
pattern 为正则表达式。string 为要匹配的字符串。Maxsplit 为分割次数,默认为 0 不限次数
import re
s = re.split('W+', 'www.huawei.com') #W+表示匹配非英文和数字一次或多次
print(s)
['www', 'huawei', 'com']
2.2 装饰器
本质是一个 Python 函数,对函数的功能进行扩展,以@开头
#现有一个函数,输出 I am learning Decorators.
def test():
print ("I am learning Decorators.")
test()
I am learning Decorators.
#装饰器函数decorator()
def decorator(func):
def wrapper():
print ("I learned Python Data Structures.")
func()
return wrapper
@decorator
def test():
print ("I am learning Decorators.")
test()
I learned Python Data Structures.
I am learning Decorators.
2.3 生成器
通过循环逐步获取集合后续的元素,yield 的函数被称为生成器(generator),可以降低内存占用
#使用圆括号编写生成器
G = ( x*2 for x in range(5)) #这里表示从 range(5)中每个 x*2
print(type(G))
for i in G:
print (i)
<class 'generator'>
0
2
4
6
8
迭代器,是将一个集合的所有元素依次遍历。
而生成器返回的是一个迭代器,函数每次碰到 yield 关键词,就会把此关键字后面的值 添加进这个要返回的迭代器中,然后把生成器生成的这个 迭代器返回
# 使用 yield 关键字创建一个生成器
def fib(n):
current, num1, num2= 0, 0, 1 #初始化数值从 0,1 开始,current 为循环
while True:
if current > n: #大于参数结束循环
return
yield num1 #yield 将函数变为一个生成器,函数不断循环
num1, num2 = num2, num1+num2
current += 1
fib(5)
for i in fib(5):
print (i)
0
1
1
2
3
5
唤醒生成器
可以使用 next 和 send 方法唤醒生成器,相比于 next 方法,send 在唤醒生成器时还可以向断点
处传入一个数据。
def gen():
i = 0
while i<5:
temp = yield i
print(temp)
i+=1
f = gen()
next(f)
f.send('haha')
next(f)
haha
None
2
2.4迭代器
可以记住遍历位置
的对象。迭代器从第一个元素开始访问,直到所有元素被访问完结束。
#使用 isinstance()方法判断对象是否是可迭代对象
from collections import Iterable # 可迭代对象
print(isinstance([], Iterable))
print(isinstance('abc', Iterable))
print(isinstance({'a':1,'b':2},Iterable))
print(isinstance(100, Iterable))
True
True
True
False
<ipython-input-10-a0aa53d20682>:2: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
from collections import Iterable # 可迭代对象
#通过 iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用 next()函数来获取下一条数据
l = [1, 2, 3, 4, 5]
l_iter = iter(l)
next(l_iter)
next(l_iter)
next(l_iter)
3
#类里实现__iter__()和__next__()方法,可以实现一个迭代器。
#StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况
class Count: # 声明一个类实现迭代器
def __iter__(self): # 实现__iter__方法
self.a = 1 # 初始值为 1
return self
def __next__(self): # 实现__next__方法,功能能为+1
if self.a <= 5:
x = self.a
self.a += 1
return x
else:
raise StopIteration # 迭代完成
mycount = Count()
myiter = iter(mycount)
for i in myiter: # 使用 for 循环遍历迭代器
print (i)
1
2
3
4
5
2.5 多任务
多任务分为多线程和多进程。
线程通常位于进程
里面,由一个程序计数器、一个堆栈、一组寄存器和一个标识符组成
多线程:
线程同步,引入锁的概念,访问前锁定;
同步阻塞
#多线程可以用 threading 模块实现
import threading
from time import sleep,ctime # sleep 可以指定程序等待时间,ctime 可以返回本地时间
def work1(): # 定义函数 work1,间隔 1 秒输出 work1 字符串
for i in range(3):
print("work1 正在执行...%d"%i)
sleep(1)
def work2(): # 定义函数 work2,间隔 1 秒输出 work2 字符串
for i in range(3):
print("work2 正在执行...%d"%i)
sleep(1)
if __name__ == '__main__':
print('---开始---:%s'%ctime())
t1 = threading.Thread(target=work1) # 线程 1 调用 work1
t2 = threading.Thread(target=work2) # 线程 2 调用 work2
# 启动线程
t1.start()
t2.start()
sleep(5)
print('---结束---:%s'%ctime())
---开始---:Mon Apr 26 19:48:10 2021
work1 正在执行...0
work2 正在执行...0
work1 正在执行...1work2 正在执行...1
work1 正在执行...2work2 正在执行...2
---结束---:Mon Apr 26 19:48:15 2021
#使用 Lock 可以实现简单的线程同步,这个对象有 acquire 方法和 release方法。
import threading
import time
g_num = 0 # 定义一个全局变量赋值为 0
def test1(num): # 定义函数 test1,对全局变量执行加操作
global g_num # 使用全局变量
for i in range(num):
mutex.acquire() # 上锁
g_num += 1
mutex.release() # 解锁
print("---test1--- g_num=%d" %g_num)
def test2(num): # 定义函数 test2,同样对全局变量加操作
global g_num
for i in range(num):
mutex.acquire() # 上锁
g_num += 1 # 执行加操作
mutex.release() # 解锁
print("---test2--- g_num=%d" %g_num)
# 创建一个互斥锁
# 默认是未上锁的状态,可以删除锁后查看资源争夺的结果
mutex = threading.Lock()
# 创建 2 个线程,让他们各自对 g_num 加 1000000 次
p1 = threading.Thread(target=test1, args=(1000000,))
p1.start()
p2 = threading.Thread(target=test2, args=(1000000,))
p2.start()
# 等待计算完成
time.sleep(5)
print("2 个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
---test1--- g_num=1946509
---test2--- g_num=2000000
2 个线程对同一个全局变量操作之后的最终结果是:2000000
5.2 多进程
#coding=gbk #编码声明
from multiprocessing import Process
import os
import time
nums = [11, 22] #设置全局的变量
def work1():
"""子进程 1 要执行的代码,对 nums 列表进行扩展"""
print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums)) # 获取进程号
for i in range(3):
nums.append(i)
time.sleep(1)
print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums))
def work2():
"""子进程 2 要执行的代码,输出进程号和调用 nums 列表"""
print("in process2 pid=%d ,nums=%s" % (os.getpid(), nums))
if __name__ == '__main__':
p1 = Process(target=work1)
p1.start()
p1.join() #等此线程执行完后,再执行其他线程
p2 = Process(target=work2)
p2.start()