目录
快捷键
快捷键 | 作用 |
ctrl + 单击 | 打开内置函数详情 |
ctrl + / | 将框选的代码注释/取消注释 |
tab | 将框选代码缩进一级 |
shift + tab | 将框选代码取消缩进一级 |
ctrl + f | 在目标处打开搜索栏 |
# 注释内容 | 单行语句注释 |
"""注释内容""" | 多行语句注释 |
格式输出
普通输出
print(f'...{变量}...')
print('...%d...%f...%s...', % (整型变量,浮点变量,字符变量))
print('...{}...'.format(变量))
特殊输出
print('..."双引号内容"...\'单引号内容\'...') #含引号数据的输出
print('...%.3f...%06d...', % (变量1,变量2)) #输出3位小数,6位整数(前面用0补齐)
print('...\n...\t...') #换行符,制表符Tab
print('...',end='结束符') #设置结束符,默认\n
变量类型
可变类型:列表、集合、字典
不可变类型:整型、浮点型、字符串、元组
type(数据) #检测数据类型
int(数据) #转换为整型
str(数据) #转换为字符型
list(数据) #转换为列表
set(数据) #转换为集合
tuple(数据) #转换为元组
chr(数据) #ASCII转字符或Unicode转中文
ord(数据) #字符转ASCII或中文转Unicode
eval(数据) #字符串中有效数据自动转型
a,b=b,a #变量值互换
id(变量) #变量地址
运算
+ #加
- #减
* #乘
/ #除
// #整除
% #取余
** #指数
() #优先级
= #赋值
变量1,变量2=数据1,数据2 #多变量分别赋值
变量1,变量2=数据 #多变量赋相同值
c运算符=a #运算后赋值给c,例如c%=a等价于c=c%a
== #判断相等
!= #判断不等
>与< #大于与小于
>=与<= #大于等于与小于等于
and #与运算
or #或运算
not #非运算
循环与判断
if 条件语句
格式:
if条件1:
条件1成立时的任务
elif条件2:
条件2成立时的任务
else:
所有条件均不满足时的任务
三目运算:
c = 返回值1 if 条件 else 返回值2 #若条件成立赋值1,否则赋值2
例如:
c = a if a>b else b # c等于a和b中较大者
while循环语句
格式:
while 条件1: #当满足条件1时,执行循环
任务1
if 条件2: #当满足条件2时,跳出此层循环
任务2
break
if 条件3: #当满足条件3时,结束此次循环,直接进入下一次循环
任务3
continue
if 条件4: #当满足条件4时,跳出所有循环,结束进程
任务4
return
任务5 #上述条件均不成立时执行此任务
else:
任务6 #循环正常完成后的任务,若循环不开始或者跳出,则不执行
任务7 #循环外的任务
注意:
如果是限次循环,需要重复n次,初始值为c,则条件是<n+c
一般在循环最后进行 i+=1 的操作,注意continue所对应的任务中需要单独进行 i+=1 的操作
while语法常常用于需要持续执行任务,或者需要等待触发等情况
如果while中还有内部循环,可通过break跳出当前层循环,或者return跳出所有循环结束进程
while True:
任务1
if 触发条件:
任务2
break
任务3
for i in range(100):
任务4
if 跳出此层循环条件:
任务5
break
if 跳出所有循环条件:
任务6
continue
任务7
for遍历语句
格式:
for 临时变量 in 序列:
任务1
if 条件2: #当满足条件2时,跳出此层循环
任务2
break
if 条件3: #当满足条件3时,结束此次循环,直接进入下一次循环
任务3
continue
if 条件4: #当满足条件4时,跳出所有循环,结束进程
任务4
return
任务5 #上述条件均不成立时执行此任务
else:
任务6 #循环正常完成后的任务,若循环不开始或者跳出,则不执行
任务7
序列操作
字符串 str
格式 | 作用 | |
str[i] | 索引第 i 位字符 | |
str[m,n,b] | 索引 [m,n) 范围内按步长b切片 若m、n为负数表示反向索引,倒数第m位 若b为负数表示反向切割 | |
str.split(子串或字符, 次数) | 切割掉子串或字符,剩余部分以列表返回 | |
str.replace(旧子串, 新子串, 次数) | 将旧子串替换为新子串 当新子串为空时,可作为删除子串使用
| |
str.remove(子串) | 移除首个指定子串 | |
str.clear() | 清空字符串变量 | |
str.append(子串) | 末尾添加子串 | |
str.insert(索引, 子串) | 在索引处插入子串 | |
str.find(目标子串, m, n) | 索引 [m,n) 范围内查找子串首次出现的索引 rfind表示从右往左查找 若未找到返回-1 | |
str.index(目标子串, m, n) | 索引 [m,n) 范围内查找子串首次出现的索引 rindex表示从右往左查找 若未找到报错 | |
str.count(目标子串, m, n) | 统计 [m,n) 范围内子串出现的次数 | |
str.strip() | 两侧删除空白字符 rstrip()删除右侧空白 lstrip()删除左侧空白 | |
str.capitalize() | 字符串首字符大写 | |
str.title() | 字符串中所有单词首字母大写 | |
str.upper() | 所有小写转大写 lower()所有大写转小写 | |
str.ljust(数据长度, '填充内容') | 数据长度内左对齐,不足时自动填充 rjust(数据长度, '填充内容')右对齐 center(数据长度, '填充内容')居中对齐 | |
str.startswith(子串, m, n) | 判断 [m,n) 范围内是否以子串开始 endswith(子串, m, n)判断结束 | |
str.isalpha() | 判断是否全部由字符构成 isdigit()判断是否全部由数字构成 isalnum()判断是否全部由数字、字符构成 isspace()判断是否全部由空格构成 | |
子串 in str | 判断是否含有子串 not in判断不含子串 | |
'起始字串'.join(字串列表) | 将列表中的所有字串合并成一个字符串 | |
str.reverse() | 将字符串逆序 | |
str.copy() | 复制,str变化,则变量同时变化 | |
len(str) | 字符串长度 | |
str1 + str2 | 合并两个字符串 |
列表 list
常用的批量存储
格式:[数据1, 数据2, ..., 数据n]
元组 tuple
元组数据不能修改
格式:(数据1, 数据2, ..., 数据n)
格式 | 作用 |
tuple() | 创建空元组 |
tuple.index(i) | 索引第 i 位元素 |
tuple.count(元素) | 元素出现次数 |
len(tuple) | 元组容量 |
tuple1 + tuple2 | 元组合并 |
集合 set
无重复数据存储,常用于去重
格式:{数据1, 数据2, ..., 数据n}
格式 | 作用 |
set() | 创建空集合 |
set.add(数据) | 添加元素 |
set.update(list) | 添加数据序列 |
set.remove(数据) | 删除元素 |
set.discard(数据) | 删除元素 |
set.pop() | 随机删除元素,并返回该元素 |
字典 dict
以键值对的形式对应存储数据
格式:{'key1': 数据1, 'key2': 数据2, ... ..., 'key': 数据}
格式 | 作用 |
dict{} | 创建空字典 |
dict[key] = 数据 | 更改数据/添加键值对 |
dict[key].del() | 删除键值对 |
dict.clear() | 清空字典 |
dict.get(key, 返回值) | 按key查找,若未找到返回设定值,默认为None |
dict.keys() | 获取key列表 |
dict.values() | 获取数据列表 |
dict.items() | 拆包字典,返回 [(key1, 数据1), (key2, 数据2), ...] |
推导式
list = [i for i in range(10)]
list = [i for i in range(10) if i % 2 == 0] #附带条件
list = [(i,j) for i in range(3) for j in range(3)] #for循环嵌套,返回元组(i,j)
dict = {key : i**2 for i in range(5)}
dict = {list1[i] : list2[i] for i in range(len(list1))} #双列表构成字典
dict = {key : value for key,value in dict.items() if value >= 200} #字典过滤
生成器与迭代器
可迭代对象
生成器gen、迭代器iter、列表list、元组tuple、字符串str、集合set、字典dict
判断是否可迭代:
from collections import Iterable
isinstance(对象, Iterable)
迭代器
可以被next()调用并返回下一个值的对象,称为迭代器iteration
iter(可迭代对象) #将可迭代对象转化为迭代器
生成器
近似等同于推导式,但节省内存,即用即推
g=推导式
g.__next()__ # 通过调用生产元素,每次调用生产一个,顺序向下
next(g) # 同上
def func:
...
yield g # 定义g为生成器,等效于"returng并暂停保存g"
g.send(值) # 向生成器传值,初次传入None
通过下面的代码加深理解
"""
费莫纳契数列【1,1,2,3,5,8,13。。。】
"""
def Femonacci(length): # 费莫纳契数列元素生成器
a,b=0,1
n=0
while n < length:
yield b
a,b=b,a+b
n+=1
return 'no rest'
byte = 8 #数列长度
Fmnc_list = []
g = Femonacci(byte)
for i in range(byte): #循环调用生成器,自动生成指定长度的数列
element = next(g)
print(element,end='')
Fmnc_list.append(element)
print('\n',Fmnc_list)
#...............................................................................
"""
利用生成器进行多协程工作,让多种工作交替执行,或分组执行
"""
def task1(j):
for i in range(j):
print(f'正在搬第{i}块砖')
yield None
def task2(j):
for i in range(j):
print(f'听第{i}首歌')
yield None
n = 5
g1 = task1(n)
g2 = task2(n)
while True:
try:
g1.__next__()
g2.__next__()
except:
pass
三者关系
生成器 ∈ 迭代器 ∈ 可迭代对象
除迭代器外,可迭代对象还包括 列表、元组、集合、字典、字符串
函数与装饰器
函数定义
def func(参数): #定义函数
"""说明文档"""
任务
return 返回值
help(func) #查看函数说明文档
global 变量 #函数内声明全局变量,函数有权修改变量值
def func(参数1,参数2): #多变量函数定义
pass
func(数据1,数据2) #函数调用,位置传参
func(参数1=数据1,参数2=数据2) #函数调用,关键词传参
def func(参数1,参数2=默认值): #定义带默认参数值的函数
pass
func(数据1) #缺省默认参数
func(数据1,数据2): #默认参数修改
def func(*args,**kwargs): #设置可变参数和可变关键字参数,任意格式参数
pass
简化函数
以map、lambda、filter、reduce、sorted为例
"""
利用lambda匿名函数进行偶数判断
用map自动将list1中的元素进行函数处理
"""
list1 = [1,2,4,6,4,6,3,8,6,4,6,3,9]
result1 = map(lambdax : x if x % 2 == 0 else x + 1, list1)#嵌套函数简化
print(list(result1))#结果转换为列表格式输出
"""
利用lambda匿名函数进行求和
用reduce自动将tuple中的元素进行函数处理
"""
from functools import reduce
tuple1 = (3, 5, 7, 8, 9, 1)
result2 = reduce(lambda x, y : x + y, tuple1, 10)
#初始值为10,对元组tuple1内所有元素,进行加法处理
print(result2)
"""
利用lambda匿名函数进行判断大于10
用filter自动将list2中符合体条件的元素存入新列表
注意:filter不改变原列表
"""
list2 = [12,6,8,98,34,36,67,3,0]
result3 = filter(lambda x : x > 10, list2) #对list2中所有元素筛选出大于10的元素
print(list(result3)) #将结果转换为列表格式
"""
利用lambda匿名函数调取字典中的age数据
用sorted自动将字典中的元素(列表)排序
"""
dict1 = [{'name': 'Tom', 'age': 24}, {'name': 'Lily', 'age': 17},{'name': 'Jerry', 'age': 20},{'name': 'Golf', 'age': 7}]
result4 = sorted(dict1, key=lambda x : x['age'], reverse=False)
#对字典中age数据进行正序排列
print(result4)
递归函数
"""
利用递归调用的方法,求10——0的和
递归函数:1)有始有终
2)自己调用自己
"""
def func1(n):
if n==0:
return0
else:
return n + func1(n-1)
print(func1(10))
递归函数条件:
自己调用自己、加判断作为终点(出口)、有初值(入口)
装饰器
主要用于触发强制执行,例如页面需要登录才能进一步访问
def func1:
def func2:
pass
return func2
@func1:
def func3:
pass
func3
工作原理:顺序定义 调用func3 找到func3所在装饰器func1 找到func1 执行func1下属的所有函数和代码(包括func2)
而对于以下代码
@decorate1
def func:
pass
@decorate2
def func:
pass
func
多次装饰器,采用就近优先的原则,执行decorate2
装饰器sh:登录付款系统
"""
登陆状态判断,以及强行跳转,采用装饰器
需要强行跳转的函数,在其定义前使用装饰器@函数名
此处是在付款函数的定义前加登陆验证判断
装饰器是将函数作为参数,传入装饰器函数中,相当于调用被装饰函数=调用装饰器内部所定义的函数
"""
import time #导入时间库
islogin = False #登陆状态,默认未登陆
#登陆界面
def login():
username = input('输入用户名:')
password = input('输入密码:')
if username == 'admin' and password == '123456':
#用户名、密码核对正确,更改登录状态为True
return True
else:
return False
#验证付款登陆(装饰器)
def login_required(func):
def wrapper(*args,**kwargs): #wrapper的参数格式可变
global islogin #后面会更改全局变量islogin的值,需要声明
print('------------付款---------------')
#验证登陆
if islogin: #若登陆成功,执行func,即执行pay
func(*args,**kwargs)
else: #若未登陆,进入login
print('用户未登陆,不能付款')
islogin=login()
print('result:',islogin)
return wrapper#表示func=wrapper,即pay=wrapper
#验证付款
@login_required #调用付款函数前需要验证,类似于login_required(pay)
def pay(money):
print(f'正在付款,付款金额为:{money}')
print('付款中。。。')
time.sleep(2)#延时2s
print('付款完成')
#付款操作
while True:
pay(input('输入付款金额'))#只有登录状态,才能执行付款
常用函数
range(数字) #[0,n)中整数列表
reage(m, n, b) #[m,n)中整数列表,步长为b
input('输入提示') #输入
del() #删除变量
pop() #删除变量,返回数据
max() #获取最大值
min() #获取最小值
常用三方库
名字 | 作用 |
builtins | 内建函数,默认加载 |
math | 数学库 |
random | 生成随机数 |
time | 时间 |
datetime | 日期、时间 |
calendar | 日历 |
hashlib | 加密算法 |
copy | 拷贝 |
functools | 常用工具 |
os | 操作系统接口 |
re | 字符串正则 |
sys | python自身的运行环境 |
multiprocessing | 多进程 |
threading | 多线程 |
json | 编码和解码 json对象 |
login | 记录日志、调试 |
随机数
import random
random.random() #随机地址
random.randrange(1,10,2) #产生整型随机数,从1到10,步长2
random.randint(1,10) #产生整型随机数
list1 = ['red', 'yellow', 'blue', 'green', 'black']
random.choice(list1) #随机列表内元素
random.shuffle(list1) #洗牌动作,打乱列表
print(list1)
例如,生成随机验证码:
#验证码生成,包含大写字母和数字
def func():
code=''
for i in range(4):
ran1 = str(random.randint(0,9)) #随机数字
ran2 = chr(random.randint(65,90)) #随机大写字母(对应ASCII码)
ran3 = chr(random.randint(97,122)) #随机小写字母
r = random.choice([ran1,ran2,ran3]) #随机选择数字、大小写字母
code += r #组成四位随机字符串
return code
code1 = func()
print(code1)
时间
import time
time.sleep(n) #延时n秒
t=time.time() #时间戳,当前时间数值,单位秒,浮点型
print(t)
print(time.ctime()) #当前时间,字符串
print(time.localtime().tm_mon) #当前时间,元组(当前取出月份)
print(time.strftime('%Y-%m-%d%H:%M:%S')) #自定义格式时间,对应格式见函数内(Ctrl+点击)
日期时间
import datetime
print(datetime.date.today()) #当前日期
pretime = datetime.datetime.now() - datetime.timedelta(hours=2) #两个小时前的时间
print(pretime)
哈希加密
#单向(md5、sha1、sha256)
#可加可解(base64)
import hashlib #哈希加密库
msg1 = '加密文件'
msg_code = msg1.encode('utf-8') #信息编码
msg_md5 = hashlib.md5(msg_code) #对编码后的信息进行md5加密
print(msg_md5.hexdigest()) #以16进制表示加密后的信息
msg_sha1 = hashlib.sha1(msg_code) #对编码后的信息进行sha1加密
print(msg_sha1.hexdigest())
msg_sha256 = hashlib.sha256(msg_code) #对编码后的信息进行sha256加密
print(msg_sha256.hexdigest())
加密应用项目:
#密码加密举例
password = '123456' #设置密码
list2 = []
password_sha256 = hashlib.sha256(password.encode('utf-8')) #对密码进行编码、sha256加密
list2.append(password_sha256.hexdigest()) #将加密后的密码添加至密码列表中
pwd = input('输入密码:') #用户输入
pwd_sha256 = hashlib.sha256(pwd.encode('utf-8')) #对输入信息进行编码、sha256加密
pwd=password_sha256.hexdigest() #将加密后的用户输入,用16进制表示
print(pwd)
for i in list2: #遍历密码列表,若加密后的用户输入和密码列表能对应,则登陆成功
if pwd == i:
print('登陆成功')
文件处理
python进行文件的读取写入操作需要借助数据流,相当于创建一个中间级,将数据以暂存的方式传输
with open('文件路径',mode='mode') as stream:
文件操作
文件操作
文件路径包括 绝对路径和相对路径
绝对路径:从硬盘开始,到文件名
相对路径:同级直接写文件名,上级加 ../ ,下级加 /
模式mode包括:
r 纯文本文件读取
w 纯文本文件写入,会清空原有记录
rb 二进制读取,支持文本、图片、音乐、视频等
wb 二进制写入,支持文本、图片、音乐、视频等,会清空原有记录
a 添加,不清空原有记录
x 新建,文件已存在会报错
文件操作包括:
#读操作
open(path/filename,'r') #创建读取流,返回stream(流)
stream.read() #读取信息
stream.readable() #是否可读
stream.readline() #读取一行
stream.readlines() #按行读取,返回列表
#写操作
open(path/filename,'w') #创建写入流,返回stream(流)
stream.write() #写入信息
stream.writeline() #写入行
stream.writelines([]) #依次写入列表中的元素
#添操作
open(path/filename,'a') #创建添加流,返回stream(流)
stream.write() #写入信息
stream.writelines([]) #依次写入列表中的元素
#新建操作
open(path/filename,'x') #创建新建&写入流,若已存在会报错
#关闭流,释放内存
stream.close()
文件复制:
# 单个文件复制
with open('文件路径','rb') as stream1:
变量 = stream1.read()
with open('新文件路径','wb') as stream2:
stream.write(变量)
#文件夹下所有文件复制
import os#导入os库
def copyfiles(src,target) #(封装函数)
if os.path.isdir(src) and os.path.isdir(target):
#判断src和target是否为有效路径
filelist = os.listdir(src)
for file in filelist: #遍历src路径下所有文件
path = os.path.join(src,file) #将文件夹和文件名组合成绝对路径
with open(path,'rb') as stream1: #复制操作,将所有文件复制至target路径
container = stream1.read()
path1 = os.path.join(target,file)
with open(target,'wb') as stream2:
stream2.write(container)
else: #结束复制
print('复制完毕')
文件路径相关
stream.name() #流所对应的路径
file.rfind('str') #文件路径(字符串)从右开始,str首次出现的位置
file.lfind('str') #文件路径(字符串)从左开始,str首次出现的位置
file[file.rfind('\\')+1:] #file文件名
import os #os模块(operatesystem操作系统,往往与路径相关)
os.path.join(path,'str') #将已有路径后加上str部分
os.path.isabs(path) #判断是否是绝对路径
os.path.isdir(path) #判断是否是文件夹
os.path.dirname(__file__) #当前文件所在文件夹的路径
os.path.abspath(path) #相对路径转换为绝对路径
os.path.split(path) #得到元组(文件夹路径,文件名)切割出文件名
os.path.splitext(path) #得到元组(文件路径,文件类型)切割出文件扩展名
os.path.getsize(path) #获取文件大小,单位字节
os.path.exists(path) #判断文件是否存在
os.getcwd() #当前文件所在文件夹的路径
os.listdir(path) #返回目录中所有文件和文件夹名字列表
os.mkdir(path) #路径下创建文件夹(已有文件会报错)
os.rmdir(path) #移除文件(只能删除空文件夹)
os.removedirs(path) #移除目录下空文件
os.remove(path) #删除文件
os.chdir(path) #将当前文件路径更换至指定路径(进入指定目录)
文件操作小项目1:
需要创建对应的 user.txt
"""
注册登录系统:
用户登录,在用户信息储存文件中核对用户名和密码,判断是否正确
用户注册,成功注册后会将新用户信息写入用户信息储存文件
"""
def register():
username = input('输入用户名:')
password = input('输入密码:')
repassword = input('再次输入密码')
if password == repassword:
with open(r'C:\path\user.txt','a') as wstream:
wstream.write('{}{}\n'.format(username,password))
print('注册成功')
login()
else:
print('注册失败,请重新注册')
return register()
def login():
username = input('请输入用户名')
password = input('请输入密码')
input_info = '{}{}\n'.format(username,password)
if username and password:
with open(r'C:\new_path\user.txt','r') as rstream:
user_infos = rstream.readlines()
if input_info in user_infos:
print('登录成功')
else:
print('用户名或密码错误')
choise = input('1、重新登录2、注册')
if choise == '2':
register()
else:
return login()
login()
文件操作小项目2:
复制文件夹内所有内容,包括图片、文本、内部文件夹
import os
def cpfiles(src_path,target_path):
filelist = os.listdir(src_path) #获取文件夹内的文件,得到文件列表
for file in filelist: #遍历文件列表
path=os.path.join(src_path,file) #拼接路劲
if os.path.isdir(path): #判断是否为文件夹
nfile_path = os.path.join(target_path,file) #拼接路径
os.mkdir(nfile_path) #创建新文件夹
cpfiles(path,nfile_path) #对文件夹内容,递归
else: #不是文件夹,复制
with open(path,'rb') as rstream: #创建读取流
container = rstream.read() #读取内容
target_file = os.path.join(target_path,file) #拼接路径
with open(target_file,'wb') as wstream: #创建写入流
wstream.write(container) #粘贴内容
else: #遍历完成,复制完成
print('复制完成')
cpfiles(r'C:\path\file_test', r'C:\path\copy_test')
TRY及异常处理
try用于进行代码尝试,针对可能报错的代码,进行尝试执行,如果报错,进行预设处理,不会让代码停下,而是继续执行
try:
可能出现异常的代码
return 1
except error1 as err: #异常1时获取异常说明err
异常1时执行的代码
print(err)
except error2:
异常2时执行的代码
return 2
else:
无异常时执行的代码
finally:
无论是否异常都会执行的代码
return 3 #会覆盖前值,返回3
代码报错会优先父辈,为了便于排查错误,对于except对应的错误,按辈分从低到高顺序排列,最泛泛的error放在最后
自定义函数时,可通过自定义异常条件及异常说明,便于调用时进行错误提示和进行try操作
def register():
username = input('输入用户名:')
if len(username) < 6:
raise Exception('用户名长度必须6位以上') #抛出异常与异常说明
else:
print('输入的用户名是:',username)
try:
register()
except Exception as err: #运行异常,获取异常说明
print(err)
print('注册失败')
else:
print('注册成功')
类 CLASS
类: 将具有公共属性及方法的变量定义为类
类属性: 类自身固有的性质、变量及默认值,以及不可修改值
对象属性:定义在类中的属性,每个对象拥有不同属性值
类方法: 定义在类中的函数,参数为cls,调用时用 对象.方法,可用于修改不可修改类属性
@classmethod
def 方法名(cls,[参数]):
内容
类名.方法名()
对象.方法名()
对象方法:定义在类中的函数,参数为self,调用时用 对象.方法(变量值),不可调用类方法,不改变类属性默认值
魔术方法:触发自动执行
init 动态定义所有属性变量,并用传入的值赋于变量,
new 优先执行,开辟一块内存存储类,返回值作为self
call 让对象可作为函数调用,内容为call下代码
del 删除相同对象的引用(一般不用)
str 调用对象可以给出对象信息
静态方法: 无需传参,只能访问类方法和类属性,无法访问对象
@staticmethod
def 方法名():
内容
类名.方法名()
对象.方法名()
类之间关系(继承): is a 与 has a
类的定义与调用示例:
class Cat: #定义类
type='猫' #定义类属性及默认值
name='小猫'
__sex='man' #定义类属性不可更改,类外无法直接修改
def __init__(self,name,age): #定义初始化魔术方法,以及动态属性变量(属于对象方法)
print('---------->init')
self.age = age #将传入的变量值赋给对象属性
##注意:此时name没有赋值,沿用默认值
def __new__(cls,*args,**kwargs): #优先执行,新开辟一块内存,返回值作为self
print('---------->new')
return object.__new__(cls) #返回内存位置,并作为self
def __call__(self,parameter): #调用执行,将对象类似于函数调用
print('---------->call')
print('外界传入的name为{}'.format(parameter))
def __del__(self): #对象无引用时,执行
print('---------->del') ##注意:此方法容易覆盖python默认回收机制,一般不使用
def __str__(self): #对象的信息(不再是地址)
print('---------->str')
return '名字叫' + self.name+',年龄为' + str(self.age)
def eat(self,food): #定义对象方法及变量
print('{}正在吃{}'.format(self.name,food))
def run(self):
print('{}今年{}岁,正在玩耍'.format(self.name,self.age))
@classmethod
def test1(cls): #定义类方法(只能访问类属性、类方法)
print('------->类方法')
print(cls.name,cls.__sex) #打印类属性
@classmethod
def sex_change(cls): #定义类方法(用于修改类属性)
__sex='wuman' #修改类属性
print(cls.__sex)
return__sex #调用时返回修改后的类属性
@staticmethod
def test2(): #定义静态方法
print('------->静态方法')
print(Cat.__sex,Cat.name) #打印类属性
p1 = Cat('lisi',20) #调用类,创建对象,赋值变量,执行new
print(dir(Cat)) #类的方法、属性
print(dir(p1)) #对象方法、属性
p1.run() #调用类对象方法,使用赋值参数
p1.name = '咪咪' #覆盖属性默认值
p1.eat('老鼠') #调用类对象方法,并传递变量参数
p1.test1() #调用类方法
print(p1.sex_change()) #修改类属性sex
p1.test2() #调用静态方法
p1('inputparameter') #调用call()
print(p1)
importsys #导入sys库
p2 = p1 #增加对象引用
print(sys.getrefcount(p1)) #获取p1调用次数(包括当前操作)
delp2 #删除p2引用,获取此时p1调用次数
print(sys.getrefcount(p1))
delp1 #当引用全部删除(次数==1)则执行del内容
继承
类属性或方法的共有
class Person: #定义类:人
def __init__(self,name): #定义对象初始属性(人共有)
self.name = name
self.age = 18
def eat(self): #定义方法(人共有)
print(self.name+'正在吃饭')
class Student(Person): #定义类:学生,继承父类Person
def __init__(self,name,major): #定义对象初始属性
super().__init__(name) #子类定义init时必须包括定义父辈init
self.major=major #Student独有属性
print('--------->Student的init')
def study(self,course): #定义方法
print('{}正在学习{}课程'.format(self.name,course))
stu = Student('Jack','computer') #创建对象
stu.eat() #执行方法,方法来自Person继承
stu.study('python基础')
在继承关系中,往往有 广度优先和深度优先 两大类
当存在多级继承的情况时,python采用广度优先的新式类
"""
多继承的优先级顺序问题
python3采用新式类:广度优先
"""
class P1:
def foo(self):
print('------->P1_foo')
def bar(self):
print('------->p1_bar')
class P2:
def foo(self):
print('------->p2_foo')
class C1(P1,P2):
pass
class C2(P1,P2):
def bar(self):
print('------->c2_bar')
class D(C1,C2):
pass
print(D.__mro__) #查看搜索顺序
d=D()
d.foo()
d.bar()
封装
类属性的私有化,类外无访问权限
"""
封装:将某些属性私有化,类外无法访问
通过装饰器来授予权限
"""
class Student:
def __init__(self,age):
self.__age=age #属性私有,外界无权访问
@property #允许外界取出属性
def age(self):
return self.__age
@age.setter #为age加装饰器,防止同名方法就近调用
def age(self,age): #允许外界修改属性
self.__age = age
s = Student(50)
print(s.age)
s.age = 10
print(s.age)
多态
类下共有
属于同一个类的不同对象,可以拥有自身独有的属性
"""
多态:通过加判断来限制动作对象,只有子类才能执行方法,否则不能执行
"""
class Person:
def __init__(self,name):
self.name = name
def feed_pet(self,pet): #接受传参
if isinstance(pet,Pet): #判断是否是子类
print('{}喜欢养宠物:{},昵称是{}'.format(self.name,pet.role,pet.nickname))
else:
print('不是宠物,不能养')
class Pet:
role = '宠物'
def __init__(self,nickname,age):
self.nickname = nickname
self.age = age
def show(self):
print('昵称:{},年龄:{}'.format(self.nickname,self.age))
class Cat(Pet): #定义宠物子类,猫
role = '猫'
def catch_mouse(self):
print('抓老鼠。。。')
class Dog(Pet): #定义宠物子类,狗
role = '狗'
def watch_house(self):
print('看门。。。')
class Tigger: #定义无关类,老虎
role = '大老虎'
def eat(self):
print('太可怕了,能吃人')
cat = Cat('花花',2) #创建各类对象
dog = Dog('大黄',4)
tigger = Tigger()
person = Person('张伟')
person.feed_pet(cat) #子类执行方法
person.feed_pet(tigger) #非子类执行方法
模块
导入与自定义
模块就是具有一定功能的py文件
包就是存储纯py文件的文件夹,必须包括 __init__.py 和 各模块.py
导入模块:
1.import 模块名
模块名.变量/函数/类
2.from 模块名 import 变量/函数/类, ....
在代码中可以直接使用变量,函数,类
3.from 模块名 import *
导入该模块中所有的内容 但是如果想限制获取的内容,可以在自定义模块中使用__all__=[*允许访问的内容, ...]
4.无论是import还是from的形式,都会将模块内的所有内容加载
如果不希望其进行内部语句调用,可在自定义模块中加入:
def test():... /定义模块中的函数
func /导入模块必定执行
if func == '__main__': /当且仅当本py文件运行时执行test函数,若本py文件被调用执行,则不执行test函数
test() 在自己的模块里面__name__叫:__main__
在其他模块中通过导入的方式调用时,__name__叫;__模块名__
__init__.py文件:
当导入包的时候,默认调用__init__.py文件
作用:
1.当导入包的时候,把一些初始化的函数,变量,类定义在__init__.py文件中
2.此文件中函数,变量等的访问,只需要通过包名.函数. ...
3.结合__all__=[通过*可以访问的模块]
循环导入的情况:
模块A:
from B import funcB
def funcA:
模块B:
from A import funcA
def funcB:
模块之间相互导入,发生错误
解决方法:
1.重新架构
2.将导入的语句放入函数里面
3.将导入语句放到模块的最后
进程与线程
并发:将独立CPU运行时间拆分为若干个时间段,并将他们分配给各线程执行
并行:每一个CPU执行一个线程,两个线程互不抢占CPU资源,可以同时进行
进程:程序对于某数据集合的一次运行活动,稳定性高(一个进程崩溃,不影响其他进程)无先后执行顺序,以同时进行为目的
线程:
进程与线程:进程是分配空间,线程是分配时间
cpu包括多进程,进程包括多线程
进程往往完成计算密集型操作
线程往往完成耗时较长的任务,避免长期占用内存
协程适用于耗时操作,例如网络请求、IO操作,协程的目的在于高效利用CPU
实现多任务的方式:
1、多进程模式:平行进程争夺CPU空间
2、多线程模式:平行线程争夺进程所有空间
3、协程:微线程
进程 》线程 》协程
进程
from multiprocessing import Process
Process(target= 函数, name= 进程的名字, args= 给函数传递的参数)
process.start() 启动进程
process.run() 执行任务但不启动进程
process.terminate() 终止
#进程
#linux系统采用folk创建进程
#windows系统采用multiprocessing创建进程
import os
from multiprocessing import Process
from time import sleep
sleep_num = 0 #声明全局变量,观察结果(全局变量在平行进程中相互独立,互不影响,不共用)
#(全局变量在平行线程中共用,都可对变量进行调用处理)
def task1():
global sleep_num
while True:
sleep(1)
sleep_num += 1
print('这是子进程1',os.getpid(),'这是主进程',os.getppid(),'进程1沉睡次数=',sleep_num)
def task2(second,name):
global sleep_num
while True:
sleep(second)
sleep_num += 1
print('这是子进程2',os.getpid(),'这是主进程',os.getppid(),'进程2沉睡次数=',sleep_num,name)
def task3(second):
while True:
print(f'thisisprocess3,pleasewaitingfor{second}s')
sleep(second)
print('这是进程3')
if __name__ == '__main__': #主进程开始
print('---------start----------')
print(os.getppid()) #打印主进程pid
p1 = Process(target=task1,name='任务1')
#创建任务1为进程,task加()表示返回值,不加括号表示函数本身,此处不能加()
p1.start() #启动进程
p2 = Process(target=task2,name='任务2',args=(2,'名字是任务2'))
#进程传参:args=元组或列表
p2.start()
p3 = Process(target=task3,name='任务3',args=(3,))
p3.start()
print(p1.name) #打印进程1的名字
number = 0
while True:
number += 1
sleep(0.1)
if number == 30: #结束进程
p1.terminate()
p2.terminate()
print('进程1、2结束')
elif number == 70:
p3.terminate()
break
else:
print('number=',number) #用于观察进程运行状况
自定义进程
将进程定义为类
"""
自定义进程:
通过创建类,自定义进程的参数、内容等
通过类,创建具有相同功能的进程
"""
from multiprocessing import Process
from time import sleep
class MyProcess(Process): #把自定义进程,定义为一个类
def __init__(self,name): #通过__init__添加参数name
super(MyProcess,self).__init__()
self.name = name
def run(self): #进程运行的内容,打印并延时0.5s
n=1
while True:
print('自定义进程名字为{},n={}'.format(self.name,n))
n+=1
sleep(0.5)
i=0
if __name__ == '__main__':#主程序(主进程)
p1 = MyProcess('进程1') #按自定义进程类,创建进程
p2 = MyProcess('进程2')
p1.start() #启动进程
p2.start()
while True:
if i == 3: #当3s后结束进程
p1.terminate()
p2.terminate()
break
sleep(1) #按秒判断
i+=1
进程池
"""
进程池Pool
用于创建大量进程,初始化Pool时,指定一个最大进程数,当新的请求提交到Pool时,若池未满,自动创建新进程用来执行该请求;若池已满,则该请求等待直到池中有进程结束,则创建新进程
阻塞式:添加一个任务执行一个,任务不结束,下一个任务无法进入,当有任务结束时,接下来的任务会接替该任务的id执行,直至全部进程执行完毕
非阻塞式:进程全部添加到队列中,立刻返回,并没有等待其他的进程执行完毕,但是回调函数是等待所有任务全部完成之后才会执行,当有任务结束时,接下来的任务会接替该任务的id执行,直至全部进程执行完毕
"""
from multiprocessing import Pool
from random import random
import time
import os
container = []
def task(task_name):
print('开始做任务了',task_name)
start = time.time()
time.sleep(random()*2)
end = time.time()
print('完成任务',task_name,'进程执行用时:',(end-start),'pid:',os.getpid())
return'完成任务:{},用时:{},进程id:{}'.format(task_name,(end-start),os.getpid())
def callback_func(n):
container.append(n)
if __name__ == '__main__': #快捷键main+enter键
pool =Pool(5) #设置进程池容量
task_list = ['听音乐','吃饭','打游戏','写作业','学python','睡觉','聊天']
for i in task_list:
#pool.apply(task,args=(i,)) #阻塞式:任务、参数
pool.apply_async(task,args=(i,),callback=callback_func) #非阻塞式:任务、参数、回调函数
pool.close() #申请添加任务结束
pool.join() #主进程让步,优先pool,只有当进程池中子进程全部结束,才会结束主进程
print(container) #阻塞式无回调,非阻塞可以回调
进程间的通讯,队列
"""
进程间的通信:队列queue
q.put() 如果queue满了则只能等待,除非有空位则添加成功
q.full() 判断是否满
q.empty() 判断是否空
q.qsize() 队列空间大小
q.close() 关闭队列
q.get() 获取队列中的任务
"""
from multiprocessing import Queue
from multiprocessing import Process
import time
def download(queue):
images = ['flower.jpg','grass.jpg','sun.jpg','house.jpg','kid.jpg']
for i in images:
print('正在下载:',i)
time.sleep(0.5)
queue.put(i)
def getfile(queue):
while True:
try:
file = queue.get(timeout=3)
print('{}保存成功'.format(file))
except:
print('全部打印完毕')
break
if __name__ == '__main__':
q = Queue(5)
p1 = Process(target=download,args=(q,))
p2 = Process(target=getfile,args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
print('end')
线程
线程状态:
新建---(start)--->就绪--->运行---(此处若阻塞,即sleep,则让出进程空间,返回就绪状态)--->结束
import threading
threading.Thread(target= , name= )
th.start()
th.join()
全局解释器锁GIL
当共享数据时,由于线程运行过程中可能存在阻塞,导致抢行,产生数据不安全
全局解释器锁GIL(global interpreter lock):线程同步,保护执行中的线程,防止线程抢行导致的数据不同步,但是会牺牲运行速度
#线程:
import threading
import time
lock = threading.Lock() #创建锁
list1 = [0]*10
def task1(): #获取线程锁,如果锁被占用,则等待锁的释放
lock.acquire() #阻塞
for i in range(len(list1)): #共享数据的处理放在acquire与release之间
list1[i]=i
time.sleep(0.5)
lock.release() #释放锁,如果不释放,其他线程无法进入执行状态
def task2():
lock.acquire()
for i in range(len(list1)):
print(i)
time.sleep(0.5)
lock.release()
if __name__ == '__main__':
t1 = threading.Thread(target=task1)
t2 = threading.Thread(target=task2)
t1.start()
t2.start()
print(threading.current_thread()) #当前正在执行的线程
print(threading.enumerate()) #所有执行及等待中的线程列表
t1.join() #提高一级优先级,优先执行
t2.join() #t1,t2相同优先级,高于main
print(list1)
死锁
死锁:两个线程的执行过程中需要相互调用各自的锁,则线程1占据进程并等待锁2,而锁2的释放需要占据进程,但此时需要等待线程1释放
解决方法:
1、重构代码
2、acquire(timeout= )设置占据时间上限,等待过长则自动释放 release
#死锁
from threading import Thread,Lock
import time
lockA = Lock()
lockB = Lock()
class MyThread1(Thread):
def run(self):
if lockA.acquire():
print(self.name+'获取了A锁')
time.sleep(0.1)
if lockB.acquire():
print(self.name+'又获取了B锁,原来还有A锁')
lockB.release()
lockA.release()
class MyThread2(Thread):
def run(self):
if lockB.acquire():
print(self.name+'获取了B锁')
time.sleep(0.1)
if lockA.acquire():
print(self.name+'又获取了A锁,原来还有B锁')
lockA.release()
lockB.release()
if __name__ == '__main__':
th1 = MyThread1()
th2 = MyThread2()
th1.start()
th2.start()
生产者与消费者
生产者与消费者:两个线程之间的通信
不一定生产一个吃一个,属于抢夺行为
1、通过加锁保证数据安全
#生产者与消费者Lock版
import random
import threading
import time
Money = 10000
Lock = threading.Lock()
Time = 0
class Producer(threading.Thread):
def run(self):
global Money
global Time
while True:
produce = random.randint(500,1000)
Lock.acquire()
if Time >= 10:
Lock.release()
break
else:
Money += produce
print('生产者%s生产了%d元钱,总共%d元钱'%(threading.current_thread(),produce,Money))
Time+=1
Lock.release()
time.sleep(0.5)
class Consumer(threading.Thread):
def run(self):
global Money
while True:
consume = random.randint(1,2000)
Lock.acquire()
if Money < consume and threading.Thread.is_alive(th) != True:
print('消费者%s准备消费%d元钱,但是只剩%d元钱,钱不够'%(threading.current_thread(),consume,Money))
Lock.release()
break
else:
Money -= consume
print('消费者%s消费了%d元钱,还剩%d元钱'%(threading.current_thread(),consume,Money))
Lock.release()
time.sleep(0.5)
if __name__ == '__main__':
th = Producer(name='生产者%d'%Time)
th.start()
tc = Consumer(name='消费者')
tc.start()
print(threading.Thread.is_alive(th))
while True:
if threading.active_count() == 1:
print('='*30+'end'+'='*30)
break
2、通过condition进行数据保护,线程待机等待唤醒的方式保证数据安全
#生产者和消费者condition版线程待机等待唤醒
import random
import threading
import time
Money = 10000
Condition = threading.Condition()
Time = 0
class Producer(threading.Thread):
def run(self):
global Money
global Time
while True:
produce = random.randint(500,1000)
Condition.acquire()
if Time >= 10:
Condition.release()
break
else:
Money += produce
print('生产者%s生产了%d元钱,总共%d元钱'%(threading.current_thread(),produce,Money))
Time += 1
Condition.notify_all() #通知所有等待中的线程
Condition.release()
time.sleep(0.5)
class Consumer(threading.Thread):
def run(self):
global Money
while True:
consume = random.randint(1,2000)
Condition.acquire()
while Money < consume:
print('消费者%s准备消费%d元钱,但是只剩%d元钱,钱不够'%(threading.current_thread(),consume,Money))
if not threading.Thread.is_alive(th):
Condition.release()
return #跳出所有循环
Condition.wait() #等待
Money -= consume
print('消费者%s消费了%d元钱,还剩%d元钱'%(threading.current_thread(),consume,Money))
Condition.release()
time.sleep(0.5)
if __name__ == '__main__':
th = Producer(name='生产者%d'%Time)
th.start()
tc = Consumer(name='消费者')
tc.start()
print(threading.Thread.is_alive(th)) #判断th线程是否处于有效状态
while True:
if threading.active_count() == 1: #除主线程外无其他有效线程
print('='*30+'end'+'='*30)
break
3、设置中间介queue队列,保证数据安全
FIFO:先入后出队列
LIFO:先出后入队列
队列与堆栈取出数据的顺序相反,队列通常是先入先出,堆栈则是后入先出
#生产者和消费者Queue版线程安全队列
#队列等于排队,先到先得,先进入队列的会先被取走
#堆栈等于叠碟,后到先走,后进入堆栈的会先被取走
import threading
from queue import Queue
import time
import random
Time = 0
Condition = threading.Condition()
fruits = ['苹果','梨子','香蕉','荔枝','西瓜','榴莲','桃子']
def Producer(q):
global Time
while True:
produce = random.choice(fruits)
Condition.acquire()
if Time >= 10:
Condition.notify_all() #通知所有等待中的线程
Condition.release()
break
else:
q.put(produce)
print('生产者%s生产了%s'%(threading.current_thread(),produce))
Time += 1
Condition.notify_all() #通知所有等待中的线程
Condition.release()
time.sleep(random.random())
def Consumer(q):
while True:
Condition.acquire()
while q.empty():
print('消费者%s准备吃水果,但是没有了'%(threading.current_thread()))
if not threading.Thread.is_alive(tp):
Condition.release()
return #跳出所有循环
Condition.wait()#等待
consume = q.get()
print('消费者%s吃了%s,还剩%d个水果'%(threading.current_thread(),consume,q.qsize()))
Condition.release()
time.sleep(0.7)
q = Queue(10)
tp = threading.Thread(target=Producer,args=(q,))
tc = threading.Thread(target=Consumer,args=(q,))
tp.start()
tc.start()
while True:
if threading.active_count() == 1:
print('='*30+'end'+'='*30)
break
协程
greenlet版
#协程 pip install greenlet
import time
from greenlet import greenlet
def taskA():
for i in range(5):
print('A',i)
gb.switch() #阻塞前启动协程b,释放空间
time.sleep(0.5)
def taskB():
for i inrange(5):
print('B',i)
gc.switch() #阻塞前启动协程c,释放空间
time.sleep(0.5)
def taskC():
for i in range(5):
print('C',i)
ga.switch() #阻塞前启动协程a,释放空间
time.sleep(0.5)
if __name__ == '__main__':
ga = greenlet(taskA)
gb = greenlet(taskB)
gc = greenlet(taskC)
ga.switch()
gb.switch()
gc.switch()
gevent版
通过猴子补丁进行协程自动分配
#协程 pip install gevent 自动切换行程,不用等待IO
import time
import gevent
from gevent import monkey
monkey.patch_all() #猴子补丁:感知耗时操作,自动替换所有阻塞操作,让协程自动切换
def taskA():
for i in range(5):
print('A',i)
time.sleep(0.5)
def taskB():
for i in range(5):
print('B',i)
time.sleep(0.5)
def taskC():
for i in range(5):
print('C',i)
time.sleep(0.5)
if __name__ == '__main__':
ga = gevent.spawn(taskA)
gb = gevent.spawn(taskB)
gc = gevent.spawn(taskC)
ga.join()
gb.join()
gc.join()
正则表达式
正则表达式 Regular Expression。用于验证字符串的逻辑公式,简称re
特点: 给定一个正则表达式和另一个字符串,可以达到以下目的:
1、给定的字符串是否符合正则表达式的过滤逻辑(称为‘匹配’)
2、可以通过正则表达式,从字符串中获取我们想要的特定部分
re模块函数:
match | 从开头匹配一次 |
search | 顺序查找,只匹配一次 |
findall | 顺序查找全部,遍历所有 |
sub | 按照 (正则, 新内容, 原内容) 进行替换 |
split | 在正则处分割,返回剩余部分组成的列表 |
常用正则表达式:
\A: 表示从字符串的开始处匹配
\Z: 表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串
\b: 匹配一个单词边界,也就是指单词和空格间的位置。例如,'py\b'可以匹配'python'中的'py',但不能匹配'openpyxl'中的'py'
\B: 匹配非单词边界。'py\B'可以匹配'openpyxl'中的'py',但不能匹配'python'中的'py'
\d: 匹配任意数字,等价于[0-9] digit
\D: 匹配任意非数字字符,等价于[^\d] not digit
\s: 匹配任意空白字符,等价于[\t\n\r\f] space
\S: 匹配任意非空白字符,等价于[^\s] not space
\w: 匹配任意字母数字及下划线,等价于[a-zA-Z0-9_] word
\W: 匹配任意非字母数字及下划线,等价于[^\w]
\: 转义,将后面的第一个字符取消其特殊意义
\\: 匹配原义的反斜杠\
. : 匹配除换行符(\n)以外的所有字符
^: 匹配字符串的开始,即行首
中括号内表示取逻辑非,例如,[^0-9]等价于除了0-9以外的其他字符
$: 匹配字符串的末尾,(末尾如果有换行符\n,就匹配\n前面的那个字符),即行尾
*: 按前面的匹配模式,匹配0次或多次(贪婪模式,即尽可能多的匹配),>=0 (判断:不能出现其他内容)
+: 按前面的匹配模式,匹配1次或多次(贪婪模式),>=1 (判断:必须出现)
?: 按前面的匹配模式,匹配0次或1次(贪婪模式),0,1 (判断:可有可无,查询:非贪婪,选择最短字符串)
|: 或者,条件并列。小括号内表示整体或,例如,(abc|def)等价于abc或def
中括号内表示字符或,例如,[abc|def]等价于a、b、c、|、d、e或f
{m}: 验证按前面的匹配模式,匹配m次
{m,}: 验证按前面的匹配模式,匹配m次或多次 >=m
{m,n}: 验证按前面的匹配模式,匹配m次以上,n次以下 >=m,<=n
在*,?,+,{m,n}后面加?,转换为非贪婪,总是尝试匹配尽可能少的数据
正则表达式应用举例
import re
msg1 = 'jack334c2#^2jerry2km*&'
print(re.match(r'jack',msg1)) #match从头开始匹配,匹配成功则返回,否则返回None
print(re.match(r'[0-9a-zA-Z_]{3,}',msg1))
#match从头开始匹配,由数字、字符或下划线组成,3位及以上
print(re.search(r'jerry',msg1)) #search顺序查找匹配
print(re.search(r'jerry',msg1).span()) #匹配成功位置
print(re.search(r'[a-z][0-9][a-z]',msg1).group()) #匹配成功的内容部分,首中即停
print(re.findall(r'[a-z][0-9]+[a-z]',msg1)) #匹配成功的内容部分,找完为止
print(re.search(r'^[a-zA-Z]\w{3,}$',msg1))
#search顺序查找匹配,从头开始到末尾,以字符开头,由数字、字符或下划线组成,4位及以上
msg2 = 'a*pyb.pycc.pyd.txtepython.txt'
print(re.findall('\w*.py\\b',msg2))
#find查找所有,数字字符下划线+除换行符以外任意字符+py,且满足单词边界的字符串
#无r开头,加\表示\b不是字符格式,而是正则格式
print(re.findall(r'\w*\.py\b',msg2))
#find查找所有,数字字符下划线+.+py,且满足单词边界的字符串
#有r开头,加入\表示.不是正则格式(任意非换行字符),而是.字符
print(re.sub(r'py\b','txt',msg2)) #按正则替换
#0-100数字正则
text = '100'
print(re.match(r'\d?\d$|^100$',text))
#手机号码正则
phone = input('请输入电话号码')
if re.match('1[35789]\d{9}$',phone) != None:
print('输入成功')
else:
print('号码错误')
#邮箱正则
email = '123456789@qq.com'
print(re.match(r'\w{5,20}@(126|163|qq)\.(com|cn)$',email))
#URL正则
url = 'http://www,hao123.com'
print(re.match(r'(ftp|http|https)://\S+',url))
#爬虫正则
msg3 = '<html><h1>abc</h1></html>'
print(re.match(r'<(?P<name1>\w+)><(?P<name2>\w+)>(.+)</(?P=name2)></(?P=name1)>',msg3))
#用起名的方式进行重复项正则,(?P<名字>正则)...(?P=名字)
result1 = re.match(r'<(\w+)><(\w+)>(.+)</(\2)></(\1)>',msg3)
#进行分组,个别组的数据相同,后组引用前组内容
print(re.sub(r'<.+?>','',msg3))
print(result1)
print(result1.group(3)) #提取分组中第三组的数据,若索引为0表示返回整个数据
print(result1.group(1,2))
print(result1.groups())
#菜品涨价
def price_change(price): #菜品价格低于10元,则涨价1元
num = int(price.group())
if num < 10:
num += 1
return str(num)
pricelist = '白菜5元,香菇9元,上海青12元'
print(re.sub(r'\d+',price_change,pricelist)) #对菜品价格正则替换
print(re.split(r'\d+元,?',pricelist)) #正则剪切出菜品名
result2 = re.findall(r',?(\D+)(\d+)元',pricelist)
#利用()进行分组得到元组,利用元组获得菜品列表
print([i[0] for i in result2])
msg4 = 'thenumberis20.50'
r = re.compile(r"""\d+ #小数点前数字
\.? #小数点
\d* #小数点后面的数字
""",re.VERBOSE) #匹配格式,VERBOSE可以在后面注释
result3 = re.search(r,msg4) #按照r的格式对msg4进行匹配
print(result3.group())