一、正则表达式
1.分组匹配
import re #() 和 | #1. #+:匹配1个或者多个 print(re.search(r"\d+","abc123-d4646gshghg")) print(re.findall(r"\d+","abc123-d4646gshghg")) #*:匹配0个或者多个 print(re.search(r"\d*","abc123-d4646gshghg")) print(re.findall(r"\d*","abc123-d4646gshghg")) print("=" * 30) #2. print(re.search(r"\d+|[a-z]+","abc123-d4646gshghg")) print(re.findall(r"\d+|[a-z]+","abc123-d4646gshghg")) print("=" * 30) #3. print(re.search(r"(\d+)|[a-z]+","abc123-d4646gshghg")) """ 注意:使用findall进行搜索,如果正则中没有(),则正常匹配显示 但是,如果正则表达式中出现了(),则findall返回的数据只有()中匹配到的数据 """ print(re.findall(r"(\d+)|[a-z]+","abc123-d4646gshghg")) print(re.findall(r"\d+|([a-z]+)","abc123-d4646gshghg")) """ <re.Match object; span=(0, 3), match='abc'> ['', '123', '', '4646', ''] ['abc', '', 'd', '', 'gshghg'] """ print(re.findall(r"(\d+)|([a-z]+)","abc123-d4646gshghg")) #[('', 'abc'), ('123', ''), ('', 'd'), ('4646', ''), ('', 'gshghg')] print(re.findall(r"(\d+|([a-z]+))","abc123-d4646gshghg")) #[('abc', 'abc'), ('123', ''), ('d', 'd'), ('4646', ''), ('gshghg', 'gshghg')] print(re.findall(r"((\d+)|([a-z]+))","abc123-d4646gshghg")) #(()()) #[('abc', '', 'abc'), ('123', '123', ''), ('d', '', 'd'), ('4646', '4646', ''), ('gshghg', '', 'gshghg')] #[(外层,左边,右边)],括号的个数决定了返回的列表中元组中元素的个数 print("=" * 30) #4. print(re.findall(r"([a-z]\d)+\w+","abc123-d4646gshghg")) print(re.search(r"([a-z]\d)+\w+","abc123-d4646gshghg")) """ ['c1','d4'] #c123 d4646gshghg <re.Match object; span=(2, 6), match='c123'> """ print(re.findall(r"(([a-z]\d)+\w+)","abc123-d4646gshghg")) print(re.search(r"(([a-z]\d)+\w+)","abc123-d4646gshghg")) """ [(外层,内层),(),] [('c123', 'c1'), ('d4646gshghg', 'd4')] <re.Match object; span=(2, 6), match='c123'> """ #5. #\w可以匹配字母【大写和小写】数字和下划线 print(re.findall(r"([a-z]\d|[A-Z])+\w+","Abc123D-D4646gsHghg")) print(re.findall(r"(([a-z]\d|[A-Z])+\w+)","Abc123D-D4646gsHghg")) """ ["A","D"] Abc123D D4646gsHghg [(Abc123D,A),(D4646gsHghg,D)] """ #6. print(re.findall(r"([a-z]\d|[A-Z])+\w","Abc123D-D4646gsHghg")) print(re.findall(r"(([a-z]\d|[A-Z])+\w)","Abc123D-D4646gsHghg")) """ ['A', 'c1', 'D', 'H'] #Ab c12 D4 Hg [('Ab', 'A'), ('c12', 'c1'), ('D4', 'D'), ('Hg', 'H')] ([a-z]\d|[A-Z])+\w Ab c12 D4 Hg ([a-z]\d|[A-Z])+\w Abc1c1d5h823D-D4646gsHghg """
2.子模式
import re """ 正则表达式中的子模式 正则表达式中的()表示一个整体,同时表示子模式 如果在同一个正则表达式中出现了重复的表示规则,则后面出现的可以直接使用前面出现的规则 则从左往右将指定的规则添加(),系统会自动给()进行编号, 从1开始,当后面的规则中需要使用,则只需要使用\1,\2......表示 """ print(re.search(r"<[a-z]+><\w+>[a-zA-Z0-9]+<\w+><[a-z]+>","<div><span>hello123<span><div>")) print(re.search(r"<([a-z]+)><(\w+)>[a-zA-Z0-9]+<\2><\1>","<div><span>hello123<span><div>")) #print(re.findall(r"<([a-z]+)><(\w+)>[a-zA-Z0-9]+<\2><\1>","<div><span>hello123<span><div>"))
3.模式修正
#re.M :多行模式,影响^和$ #re.I :忽略大小写 import re #1. string = """good 123 good fhajfh good 2367856""" print(re.findall(r"^good",string)) print(re.findall(r"^good",string,flags=re.M)) """ ['good'] ['good', 'good', 'good'] """ #2. print(re.findall(r"a+","12aaaaaaa45656AAAAA")) print(re.findall(r"a+","12aaaaaaa45656AAAAA",flags=re.I)) """ ['aaaaaaa'] ['aaaaaaa', 'AAAAA'] """
4.常用函数
import re #1.compile():将一个正则字符串编译为正则对象 #功能:单独使用没有意义,一般是为了结合其他函数使用 r1 = re.compile(r"\d+") print(r1,type(r1)) #2.match():使用正则表达式匹配指定的字符串 #功能:根据指定的条件匹配指定的字符串,如果匹配上返回一个对象,如果匹配不上则返回None r2 = re.match(r"\d+","3465gg") print(r2) #3.search():使用正则表达式搜索指定的字符串 #功能:只返回第一次匹配到的结果,如果匹配上,则返回一个对象,如果匹配不上则返回None r3 = re.search(r"\d+","3465gg") print(r3) #4.findall():使用正则表达式搜索指定的字符串 #功能:返回所有匹配到的结果,返回一个列表 r3 = re.findall(r"\d+","3465gg") print(r3) print("=" * 30) #5.finditer():使用正则表达式搜索指定的字符串 #功能:返回所有匹配到的结果,返回一个迭代器,可以遍历获取其中的元素,其中的元素是匹配到的对象 r5 = re.finditer(r"\d+","25535hh-5757hhffj") print(r5) #a # print(next(r5)) # print(next(r5)) #b # for i in r5: # print(i) # print(i.group()) # print(i.span()) #6.split():使用正则表达式分割指定的字符串 #功能:使用指定的规则将指定的字符串进行分割,返回一个列表, # 如果被分割字符串有规律,则直接使用字符串的split,如果被分割的字符串没有规律,则使用re中的split str1 = "zhangsan-lisi-jack-tom" print(str1.split("-")) print(re.split(r"-",str1)) str1 = "zhangsan-----lisi---jack---------tom" #print(str1.split("-+")) print(re.split(r"-+",str1)) str1 = "zhangsan@@@@@@@@Lisi%%%Jack#############Tom&&&&&&&xiaoming" print(re.split(r"[@%#&]+",str1)) print(re.split(r"[^a-zA-Z]+",str1)) print(re.split(r"[^a-zA-Z]+",str1,2)) #7.sub和subn:使用正则表达式替换指定的字符串,类似字符串中的replace #功能:sub(old,new,string),返回替换之后的新字符串 str1 = "zhangsan@@@@@@@@Lisi%%%Jack#############Tom&&&&&&&xiaoming" #zhangsan-lisi-jack-tom" print(re.sub(r"[@%#&]+","-",str1)) #zhangsan-Lisi-Jack-Tom-xiaoming print(re.sub(r"[@%#&]+","-",str1,2)) #subn()返回一个元组,(替换之后的新字符串,统计替换的次数) print(re.subn(r"[@%#&]+","-",str1)) #('zhangsan-Lisi-Jack-Tom-xiaoming', 4)
5.注意的问题
import re #1.空格的使用 #注意:在正则表达式中注意空格的使用,也是一个字符 print(re.findall(r"\d + \w","35465gfbhjagahj")) #3 + 5 print(re.findall(r"\d |\w","35465gfbhjagahj")) #6 | 3 #2.flags的使用 #注意:但凡使用flags,则尽量使用关键字方式传参 print(re.split(r"a","a34y74Afhfha4757A666")) print(re.split(r"a","a34y74Afhfha4757A666",re.I)) #['', '34y74Afhfh', '4757A666'] print(re.split(r"a","a34y74Afhfha4757A666",flags=re.I)) #['', '34y74', 'fhfh', '4757', '666']
6.练习
import re """ 1.用户名匹配 要求: 1.用户名只能包含数字 字母 下划线 \w 2.不能以数字开头 3.⻓度在 6 到 16 位范围内 """ def check_username(name): r1 = re.match(r"^[a-zA-Z_]\w{5,15}$",name) #r1 = re.match(r"^[a-zA-Z_][a-zA-Z0-9_]{5,15}", name) if r1: return True else: return False """ 2.密码匹配 要求: 1.不能包含!@#¥%^&*这些特殊符号 2.必须以字母开头 3.⻓度在 6 到 12 位范围内 """ def check_pwd(pwd): r = re.match(r"^[a-zA-Z][^!@#¥%^&*]{5,11}$",pwd) # if r: # return True # else: # return False return True if r else False """ 4. ipv4 格式的 ip 地址匹配 提示: IP地址的范围是 0.0.0.0 - 255.255.255.255 192.168.10.45 分析: a.组成:1 2 3 b.1位:[0-9] c.2位:[1-9][0-9] 例如:5 d.3位: 1xx :[1][0-9][0-9] 2xx : [2][0-4][0-9] [2][5][0-5] """ def check_ip(ip): #一位 \d #两位 [1-9]\d #三位 # [1]\d{2} # [2]([0-4]\d|[5][0-5]) #(\d|[1-9]\d|[1]\d{2}|[2]([0-4]\d|[5][0-5]))匹配前三段的数字 #((\d|[1-9]\d|[1]\d{2}|[2]([0-4]\d|[5][0-5]))\.)匹配前三段的数字+ .,但是.本身有特殊含义,需要转义 regex = r"^((\d|[1-9]\d|[1]\d{2}|[2]([0-4]\d|[5][0-5]))\.){3}" \ r"(\d|[1-9]\d|[1]\d{2}|[2]([0-4]\d|[5][0-5]))$" r = re.match(regex,ip) print(r) return True if r else False """ 5.提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和 负数/正数: -? -有0个或者1个 小数: (\.\d+)? .有0个或者1个 整数: 1位 :[0-9] 多位: [1-9][0-9]* *可以匹配0个或者多个 [-]?(0|[1-9]\d*)(\.\d+)? """ def add(data): #如果有()findall返回[(),()],此时finditer可以直接获取到对象 r = re.finditer(r"[-]?(0|[1-9]\d*)(\.\d+)?",data) result = 0 for num in r: print(num.group()) result += float(num.group()) return result if __name__ == "__main__": #print(check_ip("10.168.10.30")) print(add("fgfg45fhj-7fhjk18.9hfh10"))
二、进程
1.概念
1.1多任务
程序的运行是CPU和内存协同工作的结果
操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统
问题1:什么是多任务?
就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已
问题2:多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?
答案:操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有c任务都在同时执行一样【现在的电脑最起码都4核起】
多核cpu实现多任务的原理:真正的并行执行多任务只能在多核cpu上实现,但是由于任务数量远远远多于cpu的核心数量,所以操作系统也会自动把很多任务轮流调度到每个核心上执行
并行:真正一起执行,任务数量小于等于cpu核心数量【理想型】
并发:看上去一起执行,任务数量多于cpu核心数量【现实型】
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程
有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)
1.2进程
是一个程序的运行状态和资源占用(内存,CPU)的描述
进程是程序的一个动态过程,它指的是从代码加载到执行完毕的一个完成过程
进程的特点:
a.独立性:不同的进程之间是独立的,相互之间资源不共享(举例:两个正在上课的教室有各自的财产,相互之间不共享)
b.动态性:进程在系统中不是静止不动的,而是在系统中一直活动的(举例:教室里一直在讲课)
c.并发性:多个进程可以在单个处理器上同时进行,且互不影响(举例:天丰利就是个处理器的话,多个教室同时上课就相当于多个进程,c相互之间不影响)
多进程:一个操作系统可以运行多个应用程序
1.3线程
是进程的组成部分,一个进程可以有多个线程,每个线程去处理一个特定的子任务
线程的执行是抢占式的,多个线程在同一个进程中可以并发执行,其实就是CPU快速的在不同的线程之间切换,也就是说,当前运行的线程在任何时候都有可能被挂起,以便另外一个线程可以运行
例如:打开酷狗音乐 ————》这是一个进程
播放歌曲和刷新歌词————》这是两个线程(两个线程在同时执行,所以说是并发的)
一个进程中的不同线程之间是资源共享的
多线程:
在一个进程中,多个线程可以同时进行
多线程是实现了并发机制的一种有效手段,一个进程中可以包含多个线程,不同线程之间是可以资源共享的,同时运行可以提高程序的执行效率,可以同时完成多个工作
应用:一个浏览器可以同时下载多张图片和多个视频
一个服务器可以同时响应多个用户请求
1.3进程和线程之间的关系【面试题】
a.一个程序运行后至少有一个进程
b.一个进程可以包含多个线程,但是至少需要有一个线程,否则这个进程是没有意义的
c.进程间不能共享资源,但线程之间可以
d.系统创建进程需要为该进程重新分配系统资源,而创建线程则容易的多,因此使用线程实现多任务并发比多进程的效率高
思考问题:前面编写的所有的Python程序,都是执行单任务的进程,也就是只有一个线程。如果我们要同时执行多个任务怎么办?
多任务的实现有3种方式:
a.多进程模式:启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务
b.多线程模式:启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务
c.协程模式
d.多进程+多线程模式:启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了
Python既支持多进程,又支持多线程,我们会讨论如何编写这两种多任务程序
2.实现
2.1单任务现象
"""
from time import sleep
def run():
#任务二
while True:
print("today is a nice day")
sleep((2))
if __name__ == "__main__":
#任务一
while True:
print("hello")
sleep(1)
#不会执行到run函数,只有上面的while循环结束才可以执行【按照顺序执行】
run()
"""
2.2启动进程实现多任务
#Python中提供了一个跨平台的多进程模块,其中的Process类可以用来创建进程对象
from multiprocessing import Process
from time import sleep
import os
#无参
def run():
#3.os.getpid()获取当前进程的进程号,os.getppid()获取当前进程的父进程的进程号
print("子进程启动~~~%s,对应的父进程:%s" % (os.getpid(),os.getppid()))
while True:
print("today is a nice day")
sleep(1.2)
#有参
def run1(num):
#3.os.getpid()获取当前进程的进程号,os.getppid()获取当前进程的父进程的进程号
print("子进程启动~~~%s,对应的父进程:%s" % (os.getpid(),os.getppid()))
print(num)
while True:
print("today is a nice day")
sleep(1.2)
if __name__ == "__main__":
#1.__main__中执行的代码表示主进程,也可以称为父进程
#注意:一个进程启动之后,系统会自动分配一个进程号
print("父进程启动-%s" % (os.getpid()))
#2.在父进程中创建子进程
#语法:Process(target,args),target表示进程执行的任务,args表示所执行任务的参数,该参数为元组
#2.1任务函数没有参数
#注意:进程对象创建完成之后,必须手动启动
#p1 = Process(target=run)
# start函数会自动调用子进程的任务函数
#p1.start()
#2.2任务函数有参数
p2 = Process(target=run1,args=(20,))
p2.start()
#父进程的任务
while True:
print("hello")
sleep(1)
2.3父子进程的执行顺序
from multiprocessing import Process
from time import sleep
import os
def run():
print("子进程启动")
sleep(3)
print("子进程结束")
if __name__ == "__main__":
print("父进程启动~~~~~")
sleep(2)
p = Process(target=run)
p.start()
#调用join函数必须在start之后
p.join() # AssertionError: can only join a started process
print("父进程结束~~~~~")
"""
结论;
a.默认情况下,父进程结束之后子进程才会被启动
b.子进程对象调用join函数完成合并,当子进程执行结束之后父进程才会结束
"""