文章目录
博客cpen_web
练习1
1、实现九九乘法表
2、实现1-100之和
3、如何跨模块共享变量
4、python中生成随机整数(1-10),随机小数(1-10),0-1随机小数的方法
5、python中哪些是可变数据类型,哪些是不可变数据类型,为什么
6、统计字符串中每个字符出现的次数
7、python实现,给定一个字符串,找到字符串中第一个重复的字符
8、重复接受一个用户输入的字符,如果是正整数,就输出结果,否则就一直输入
9、用python实现冒泡排序
1、实现九九乘法表
def lx01(): # 九九乘法表
for i in range(1, 10): # 注:range(1, 10) --> 1...9
for j in range(1, i + 1): # 注:range(1, i + 1) --> 1...i
print(f"{j}*{i}={j * i}", end=" ") # 注:end指定结尾字符串
print() # 注:print默认输出换行符
2、实现1-100之和
方法1
def lx02(): # 累加
nub = 0
for i in range(100):
i += 1
nub += i
print(nub)
方法2
print(sum(list(range(1,101)))) # 注:range(1,101)直接转换成列表使用sum进行求和
# 注:range是可迭代对象
3、如何跨模块共享变量
使用导入这个文件,调用文件里的变量,可以实现跨模块共享
4、python中生成随机整数(1-10),随机小数(1-10),0-1随机小数的方法
def lx04(): # 随机数
import random
print(random.randint(1, 10)) # 注:生成随机整数的范围
print(random.uniform(1, 10)) # 注:生成随机小数的范围
print(random.random()) # 注:生成0-1随机小数的范围
5、python中哪些是可变数据类型,哪些是不可变数据类型,为什么
# 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,就称不可变数据类型
# 包括:int(整型)、string(字符串)、tuple(元组)
# 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,就称可变数据类型
# 包括:set(集合)、list(列表)、dict(字典)
6、统计字符串中每个字符出现的次数
def lx06(): # 统计次数
str_1 = input("请输入字符串: ")
for i in set(str_1): # 注:对str进行set集合去重
print(f"字符{i}出现了{str_1.count(i)}次")
7、python实现,给定一个字符串,找到字符串中第一个重复的字符
def lx07(): # 找第一个重复字符
str_1 = input("请输入字符串: ")
for i in str_1:
if str_1.count(i) > 1:
print(f"第一个重复的字符为{i}")
return # 注:大于1时直接return退出函数
8、重复接受一个用户输入的字符,如果是正整数,就输出结果,否则就一直输入
def lx08():
while True:
str_1 = input("请输入: ")
if str_1.isdigit(): # 注:str isdigit 判断是不是只有数字
print(str_1)
else:
print("你输入的不是正整数,退出程序")
return
9、用python实现冒泡排序
def lx09():
list_1 = [46,45,13,78,65,99,45]
n = len(list_1)
# 遍历所有数组元素
for i in range(n):
for j in range(0, n - i - 1):
if list_1[j] > list_1[j + 1]:
list_1[j], list_1[j + 1] = list_1[j + 1], list_1[j]
print(f"排序后的数组为{list_1}")
def bubbleSort(arr):
n = len(arr)
# 遍历所有数组元素
for i in range(n):
# Last i elements are already in place
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
arr = [64, 34, 25, 12, 22, 11, 90]
bubbleSort(arr)
print("排序后的数组:")
for i in range(len(arr)):
print("%d" % arr[i])
示例:冒泡排序的改进 引入标志位 判定某件事情是否发生
list1 = [1,4,6,2,5,3,9,7,8]
length = len(list1) - 1
i = j = 0
while i < length:
flag = 1 # 注:标志位
print(f"第{i+1}次,list:{list1}")
j = 0
while j < length - i:
if list1[j] > list1[j + 1]:
list1[j],list1[j + 1] = list1[j + 1],list1[j]
flag = 0 # 注:有交换的情况下 flag = 0
j += 1
if flag: # 注:if flag flag=1的时候 break退出
break
i += 1
print(list1)
第1次,list:[1, 4, 6, 2, 5, 3, 9, 7, 8] # 注:改进后 只需要排序4次
第2次,list:[1, 4, 2, 5, 3, 6, 7, 8, 9]
第3次,list:[1, 2, 4, 3, 5, 6, 7, 8, 9]
第4次,list:[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Python里交换数值
>>> a = 1
>>> b = 2
>>> a
1
>>> b
2
>>> a, b = b, a
>>> a
2
>>> b
1
练习2
1、循环接收键盘输入的字符,判定是否属于正整数、负整数、浮点数 ,并给出相应提醒 按exit退出
while True:
import re
num = input("请输入:")
if re.findall(r"^\+?[1-9]\d*$",num):
print("正整数")
elif re.findall(r"^\-[1-9]\d*$",num):
print("负整数")
elif re.findall(r"^[\+|\-]?\d+\.\d+$",num):
print("浮点数")
elif num == "exit":
break
else:
print("重新输入")
2、验证密码是否合法,密码要求8-10位,以(字母或者下划线开头),给出相应提示
import re
passwd = input("请输入:")
if re.findall("^[A-Za-z_].{7,9}$",passwd):
print("密码合法")
else:
print("密码不合法")
3、提取电话号码
wen tel: 17375722991
wen tel: 173-7572-2992
wen tel: 173 7572 2993
wen tel: (+86) 17375722994
format1 = input("请提取出你输入的格式:")
import re
ret = re.search("(\(\+86\))?1\d{2}([ \-]?\d{4}){2}",format1)
print("打印:",ret)
#注:分组向后引用 ret = re.search(r"1\d{2}([ \-]?)\d{4}\1\d{4}",format1) # 注:进行分组向后引用
请提取出你输入的格式:12345678901
打印: <re.Match object; span=(0, 11), match=‘12345678901’>
请提取出你输入的格式:123-4567-8901
打印: <re.Match object; span=(0, 13), match=‘123-4567-8901’>
请提取出你输入的格式:123 4567 8901
打印: <re.Match object; span=(0, 13), match=‘123 4567 8901’>
请提取出你输入的格式:(+86)12345678901
打印: <re.Match object; span=(0, 16), match=’(+86)12345678901’>
知识点3 正则分组
正则分组-简单分组
当使用分组时,除了可以获得整个匹配,还能够获得选择每一个单独组,使用 () 进行分组
简单分组
分组不匹配(?:规则)
· 表示将()仅用于组合字符串,不识别为分组
正则分组-命名分组
命名分组:(?P规则)
正则分组-引用分组
引用分组:
·使用()分用,用\0, \1, \2引用 (\0表示匹配的整个串)
示例1:正则分组
#正则分组
import re
ret = re.search(r'(\d{3})-(\d{3})-(\d{3})',"123-321-234abc") # 注:数字匹配3次 作为1个分组
print(ret.group()) # group正则表达式能获得的所有对象
#结果为 123-321-234
print(ret.group(0)) # 0代表所有匹配的字符,不接参数 默认为0
#结果为 123-321-234
print(ret.group(1)) # 1代表第1个组 获取第1个分组
#结果为 123
print(ret.group(2)) # 2代表第2个组
#结果为 321
print(ret.group(3)) # 3代表第3个组
#结果为 234
#print(ret.group(4))
#注:报错 IndexError: no such group
#注:返回每一个单个分组的元组
print(ret.groups()) # 获取每一个分组里的值,放到1个元组里,返回1个元组
#结果为 ('123', '321', '234')
#捕获分组和非捕获分组
#分组向后引用
示例2:捕获分组
str = "a1 a2 a1 a2"
#正常的是捕获分组
#捕获分组 (分组并捕获,分组之后匹配到的数据,会放到内存中,并且给定一个从1开始的索引)
print(re.search(r"([a-z]\d ){3}([a-z]\d)", str))
#结果为 <re.Match object; span=(0, 11), match='a1 a2 a1 a2'>
print(re.search(r"([a-z]\d)\s+([a-z]\d)\s+\1\s+\2", str)) #\1跟前面分组1一摸一样 \2跟第2个分组一模一样
#结果为 <re.Match object; span=(0, 11), match='a1 a2 a1 a2'>
#分组向后引用 \1 返回的是a1[第1个分组] \2 返回的是a2[第2个分组]
#findall 有捕获分组的话,只会输出捕获分组里的内容
print(re.findall(r"([a-z]\d)\s+([a-z]\d)\s+\1\s+\2", str))
#结果为 [('a1', 'a2')]
#findall只会打印捕获分组里面的东西(a1 a2)
示例3:非捕获分组(?😃
#非捕获分组(?:) 只是分组,不捕获,不会在内存中缓存分组匹配的值,不会分配从1开始的下标索引
str2 = "a1 a2 a2 a1"
ret = re.search(r"(?:\w\d)\s+(\w\d)\s+\1", str2) # 注:非捕获分组仅仅只是给它分组 不捕获
print(ret)
#结果为<re.Match object; span=(0, 8), match='a1 a2 a2'>
#(?:\w\d)非捕获分组 不会占用下标索引
#findall
#有捕获分组的话,只会输出捕获分组里的内容
#没有捕获分组的话,输出全部内容
ret = re.findall(r"(?:\w\d)\s+(\w\d)\s+\1", str2) # 注:有捕获分组时 只会输出捕获分组里的内容
print(ret)
#结果为 ['a2']
ret = re.findall(r"(?:\w\d)\s+(?:\w\d)\s+", str2) # 注:没有捕获分组的话,输出全部内容
print(ret)
#结果为 ['a1 a2 ']
示例4:命名分组
#命名分组 # 注:命名分组合也是捕获分组 取了个名字
ret = re.search(r'(?P<name>\d{3})-\d{3}-(?P<last>\d{3})', "123-321-234abc")
print(ret.group(1))
#结果为 123
print(ret.group("name"))
#结果为 123 命令分组
print(ret.group(2))
print(ret.group("last"))
#结果都为 234 命名分组
print(ret.groupdict()) # 注:匹配到的值变为字典输出
#结果为 {'name': '123', 'last': '234'} #name就是key,取到的值是value
#获取所有匹配的字符串-字典形式
print(ret.groups()) # 注:获取所有匹配的字符串
#结果为 ('123', '234')
示例5:引用分组
#引用分组
msg = """
<div>hello</div>
<h1>hello</h1>
"""
ret = re.findall(r'(<(\w+)>hello</\2>)', msg) # 注:外面的分组是第1个 ; 里面的分组是第2个
print(ret) # 注:所以后面是 \2
#结果为 [('<div>hello</div>', 'div'), ('<h1>hello</h1>', 'h1')]
#注:一个分组 findall匹配的是一个普通元素,一个以上的分组 findall匹配结果是 元组
ret = re.findall(r'<(\w+)>hello</\1>', msg) # 注:这种与期望不符
print(ret)
#结果为 ['div', 'h1']
练习4
1、匹配里面的每一个单词,引号部分作为一个单词输出
msg = ‘san chuang tong le, huan ying ni “hello world”, learn python’
示例
import re
msg = 'san chuang tong le, huan ying ni "hello world", learn python'
ret = re.findall(r'\w+|"[\w ]+"', msg) # 注:\w+ 匹配1次到多次 "[\w ]+" 匹配1次到多次
print(ret) # 注:\w+ 匹配每一个单词
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', '"hello world"', 'learn', 'python']
#注:匹配到“就会判断是否满足第2个条件
#注:"[\w ]+" 引号里面匹配单词字符 或 空格 匹配1次到多次 "hello world"
#或者
ret = re.findall(r'"[\w ]+"', msg)
ret = re.findall(r'".*"', msg)
print(ret)
#结果为 ['"hello world"']
import re # 注:没解决问题
msg = 'san chuang tong le, huan ying ni "hello world", learn python'
ret = re.findall(r'\w+|(?<=")(?:[\w ]+)(?=")', msg) # 注:零宽断言
print(ret) # 注:没解决问题
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello', 'world', 'learn', 'python']
ret = re.findall(r'(?<=\")(?:[\w ]+)(?=")|\w+', msg)
print(ret) # 注:解决问题了 因为断言先行
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello world', 'learn', 'python']
2、msg = ‘123@qq.comaaa@126.combbb@163.comcc@abc.com’
#–> 123@qq.com aaa#126.com bbb@163.com
示例
import re
msg2 = 'yyy@xx.com123@qq.comaaa@126.combbb@163.comcc@abc.com'
# --> 123@qq.com aaa#126.com bbb@163.com
ret = re.findall("\w+@(qq|163|126).com", msg2) # 注:捕获分组
print(ret) # 注:只会捕获到分组的
#结果为 ['qq', '126', '163']
ret = re.findall("\w+@(?:qq|163|126).com", msg2) # 注:非捕获分组
print(ret)
#结果为 ['com123@qq.com', 'aaa@126.com', 'bbb@163.com']
ret = re.findall("(?:\.com)?(\w+@(?:qq|163|126)\.com)", msg2)
print(ret) # 注:从左往右依次匹配 com匹配0-1次 满足 ;匹配到com ;后面匹配0次 满足条件
#结果为 ['123@qq.com', 'aaa@126.com', 'bbb@163.com']
#先在最开始找匹配0次或1次;模板往例子里套 @xx没有被匹配到
#findall有捕获分组的情况下 只会输出捕获分组 不会输出非捕获分组 所以没有输出最前面的.com
#注:非捕获分组,不会给它索引下标
ret = re.findall("(\.com)?(\w+@(?:qq|163|126)\.com)", msg2) # 注:捕获分组 作为元组输出
print(ret) # 注:捕获分组 作为元组输出
#结果为 [('.com', '123@qq.com'), ('', 'aaa@126.com'), ('', 'bbb@163.com')]
3、输出成对存在的中间的内容(test2、test3)
#test1
#–> 输出test2 test3
示例
import re
msg3 = '<html>test1<div>test2</div><a>test3</a></html>'
# reg3 = re.findall(r"(?:<\w+>)\w+(?:</\w+>)",msg3)
ret = re.findall(r'<(\w+)>(\w+)</\1>', msg3) # 注:\1分组向后引用,表示第1个分组里面的内容
print(ret) # 注:匹配一组对应的标签
#结果为 [('div', 'test2'), ('a', 'test3')]
#捕获分组,捕获到的项会先放在内存中,并且给它一个索引从1开始
知识点5 正则标记-第三个参数
正则标记-第三个参数
第三个参数
示例
#正则标记
import re
msg = """
Python
python
"""
ret = re.findall(r"^python$", 'PYTHOn')
print(ret) # 注:匹配不上
#结果为 []
#对大小写不敏感的标志位
ret = re.findall(r"^python$", 'PYTHOn',re.I)
print(ret)
#结果为 ['PYTHOn']
ret = re.findall(r"^python$", msg,re.I)
print(ret) # 注:把msg作为字符串去匹配 ;做一个整体匹配 ; p开头n结尾
#结果为 []
#多行匹配和大小写不明感
ret = re.findall(r"^python$", msg,re.I|re.M) # 注:re.M 多行匹配
print(ret) # 注:re.M 进入 多行匹配 模式 每一行都匹配
#结果为 ['Python', 'python'] # 注:|或运算符 支持多条匹配
#re.S # 注:使.匹配包括换行在内的所有字符
ret = re.findall(r".+",msg) # 注:.任意字符匹配 \n换行符 不匹配
print(ret)
#结果为 ['Python', 'python']
#re.S
ret = re.findall(r".+",msg, re.S) # 注:使.匹配包括换行在内的所有字符
print(ret) # 注:re.S从头到为全部匹配
#结果为 ['\nPython\npython\n']
知识点6 基本正则匹配-内联标记
基本正则匹配-内联标记
内联标记
内联标记:(?imx)re
内联标记:(?imx: re)
#注:写在正则表达式前面
(?i:不区分大小写)
i 不区分大小写 # 注:不清楚
m 多行匹配 # 注:不清楚
示例
#内联标记: (?imx)re
import re
ret = re.findall('(?i)^python$', 'Python')
print(ret)
#结果为 ['Python']
ret = re.findall('(?i)^python$', 'Python\npython')
print(ret)
#结果为 []
ret = re.findall('(?im)^python$', 'Python\npython')
print(ret)
#结果为 ['Python', 'python']
#内联标记:(?imx:re)
import re
msg = "Hello Python"
ret = re.findall('(?i:hello) python', "Hello Python")
print(ret)
#结果为 []
ret = re.findall('(?i:hello) Python', "Hello Python")
print(ret)
#结果为 ['Hello Python']
练习7 提取url域名
#提取url域名
#https://music.163.com/#/discover/toplist
#http://www.baidu.com?a=1
#http://news.xinlang.cn
#http://news.xin.lang.cn
#htp://www.baidu.com # 不属于url
示例
import re
msg = """
https://music.163.com/#/discover/toplist
http://www.baidu.com?a=1
http://news.xinlang.cn
http://news.xin.lang.cn
htp://www.baidu.com
"""
ret = re.findall('(?:https?://)((?:\w+\.)+\w+)', msg,re.M)
print(ret)
#结果为 ['music.163.com', 'www.baidu.com', 'news.xinlang.cn', 'news.xin.lang.cn']
#注:(?:https?://) ?对s匹配0次或1次
#注:(?:\w+\.)+ music.163. 匹配1次以上
#注:\w+ com 匹配1次以上
#注:((?:\w+\.)+\w+) 外面这一层是捕获分组
知识点8 正则表达式断言
正则表达式断言
正则表达式的断言分为:先行断言(lookahead)和后行断言(lookbehind)
正则表达式的先行断言和后行断言一共有4种形式:
·(?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)
·(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)
·(?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)
·(?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)
零宽
· ^python
正向、负向
· 正向:匹配(?=pattern)/(?<=pattern)
· 负向:不匹配(?!pattern)/(?<!pattern)
先行、后行
· 先行:向后匹配(?=pattern)/(?!pattern)
· 后行:向前匹配(?<=pattern)/(?<!pattern)
零宽正向先行断言:(?=pattern)
· 代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern。
· 匹配字符串re,后面能接gular(但不匹配宽度)
零宽负向先行断言:(?!pattern)
· 代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配pattern。
· 匹配字符串re,但是后面不能接gular
零宽正向后行断言:(?<=pattern)
· 代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配pattern。
· 匹配gular,但前面必须是re
零宽负向后行断言 :(?<!pattern)
· 代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配pattern。
· 匹配gular,但前面不能是re
示例
#零宽断言
#匹配位置的参数不会输出
s = "a regular rbgular expression"
#零宽正向先行断言
print(re.findall(r"re(?=gular)",s)) # 注:匹配右边等于gular的re
#结果为 ['re']
#零宽断言 只匹配re gular(位置) 不占宽度gular
s = "a regularression"
# print(re.findall(r"re(?=gular)re(?=ssion)",s)) # 匹配不了2个,所以不要这么用
#结果为[]
#零宽负向先行断言
s = "a regular rbgular expression"
print(re.findall(r"re(?!gular)",s)) # 注:匹配re;后面不等于gular的re
#结果为 ['re']
s = "a regular rbgular expression"
print(re.findall(r"\w+(?=gular)",s))
#结果为 ['re', 'rb']
print(re.findall(r"\w+(?!gular)",s)) # 注:不是很理解
#结果为 ['a', 'regular', 'rbgular', 'expression']
#零宽正向后行断言
s = "a regular rbgular expression"
print(re.findall(r"(?<=re)gular",s)) # 注:匹配左边是re的gular
#结果为 ['gular']
#零宽负向后行断言
s = "a regular rbgular expression"
print(re.findall(r"(?<!re)gular",s)) # 注:匹配左边不是re的gular
#结果为 ['gular']
练习9 使用零宽断言提取ip地址
print(re.findall(r"(?<=inet ).*(?=/)"),ip)
#注:前面用零宽正向先行断言,后面用零宽负向先行断言
#注:前面加<号,后面不加<号