一、正则语法
1.贪婪和非贪婪
当匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种:
贪婪:在能匹配成功的前提下,次数尽可能多的匹配(越多越好)。默认情况下都是贪婪
非贪婪:在能匹配成功的前提下,次数尽可能少的匹配(越少越好)。在不确定的匹配次数后加?就是非贪婪。
*? 、+?、 ??、 {M,n}?、 {,N}?
fullmatch贪婪和非贪婪没有区别
re_str = '.*?abc'
print(fullmatch(re_str, 'xyxabc'))
print(fullmatch(re_str, 'xyxabc123abc'))
search的用法
re_str = r'\d\d'
print(search(re_str, 'abc34xyz89==')) # <re.Match object; span=(3, 5), match='34'>
print(search(r'.*abc', '你好920abc==-nmabc2323')) # 5, 12
# <re.Match object; span=(0, 16), match='你好920abc==-nmabc'>
print(search(r'.*?abc', '你好920abc==-nmabc2323'))
# <re.Match object; span=(0, 8), match='你好920abc'>
print(search(r'a\d+', 'shdfa8892jskks')) # a8、a88、a889、a8892
# <re.Match object; span=(4, 9), match='a8892'>
print(search(r'a\d+?', 'shdfa8892jskks'))
# <re.Match object; span=(4, 6), match='a8'>
2.检测符号
检测类的符号只做字符的检测不会进行匹配
1)\b - 检测是否是单词边界
单词边界就是任何可以区分出两个不同单词的符号,比如空白字符、标点符号、字符串开头和字符串结尾
re_str = r'abc\b123' # re_str = r'abc123'
print(fullmatch(re_str, 'abc 123')) # None
print(fullmatch(re_str, 'abc123')) # None
re_str = r'abc.\b123' # re_str = r'abc.123'
print(fullmatch(re_str, 'abc,123'))
print(fullmatch(re_str, 'abc 123'))
re_str = r'\b\d{3}\b'
print(findall(re_str, 'ahs345ksdj897四季花海345jsks345, 345, 894集 899 288 三等奖'))
# ['345', '899', '288']
2)^ - 检测是否字符串开头
re_str = r'\d{3}'
print(findall(re_str, 'ahs345ksdj897四季花海345jsks345, 345, 894集 899 288 三等奖'))
# ['345', '897', '345', '345', '345', '894', '899', '288']
re_str = r'^\d{3}'
print(findall(re_str, '7829ahs345ksdj897四季花海345jsks345, 345, 894集 899 288 三等奖'))
# ['782']
3)$ - 检测是否是字符串结尾
re_str = r'\d{3}$'
print(findall(re_str, '7829ahs345ksdj897四季花海345jsks345, 345, 894集 899 288 三等奖345'))
# ['345']
3.分支 - |
| 在正则中表示或者
正则表达式1|正则表达式2|正则表达式3|… - 让字符串先和第一个正则进行匹配如果失败再和第二个正则匹配,以此类推…
练习: 写一个正则能匹配的字符串是: abc后面是三个数字或者两个大写字母
能够匹配成功: abc234、abcHK
re_str = r'abc\d{3}|abc[A-Z]{2}'
# re_str = r'abc\d{3}|[A-Z]{2}'
print(fullmatch(re_str, 'abc342'))
print(fullmatch(re_str, 'abcKL'))
4.分组 - ()
1)把正则的部分内容堪称一个整体,进行操作
练习: 写一个正则能够匹配一个字符串是两个数字三个字母这种结构不断重复的字符串
re_str = r'(\d{2}[a-zA-Z]{3})+'
print(fullmatch(re_str, '67hsj89klo89jju90kkl'))
print(fullmatch(re_str, '89jsk90uwu'))
2)分组和\N配合使用来控制匹配内容重复
re_str = r'([a-z]{3})(\d{2})\1{3}'
print(fullmatch(re_str, 'mna99mnamnamna'))
二、re模块
1.compile(正则表达式)
编译正则表达式创建一个正则表达式对象
re_obj = re.compile(r'\d{3}')
re.fullmatch(正则表达式,字符串)
正则对象.fullmatch(字符串)
print(re_obj.fullmatch('799'))
2.匹配
1)fullmatch(正则表达式,字符串)
完全匹配,查看整个字符串是否和正则表达式匹配;匹配成功返回匹配对象,失败返回None。
2)match(正则表达式,字符串)
匹配字符串开头,查看字符串的开头是否和正则匹配;匹配成功返回匹配对象,失败返回None。
re_str = r'\d{3}'
print(re.fullmatch(re_str, '789'))
print(re.fullmatch(re_str, '789ass')) # None
print(re.match(re_str, '789是快递费akskk'))
3)匹配对象(match对象)
re_str = r'(\d{3})([a-z]{2})'
result = re.match(re_str, '234kl数据库是否')
print(result) # <re.Match object; span=(0, 5), match='234kl'>
a.获取匹配到的字符串
匹配对象.group() - 获取整个正则匹配到的结果
匹配对象.group(N) - 获取正则中第N个分组匹配到的结果
print(result.group()) # 234kl
print(result.group(1)) # 234
print(result.group(2)) # kl
b.获取匹配到的字符串在原字符串中的位置
print(result.span()) # (0, 5)
print(result.span(1)) # (0, 3)
print(result.span(2)) # (3, 5)
c.获取原字符串
print(result.string) # 234kl数据库是否
3.查找
1)search(正则表达式,字符串)
在字符串中获取第一个满足正则表达式的子串,如果找到了返回匹配对象,找不到返回None
print(re.search(r'\d{3}', 'ahdfjhj红色经典23sjd是')) # None
print(re.search(r'\d{3}', 'ahdfjhj红283色经典23sjd是')) # <re.Match object; span=(8, 11), match='283'>
print(re.search(r'\d{3}', 'ahdfj0192hj红283色经典23sjd是')) # <re.Match object; span=(5, 8), match='019'>
2)findall(正则表达式,字符串)
获取字符串中所有满足正则表达式的子串;返回一个列表,列表中的元素就是匹配到的子串
a.正则中没有分组 - 列表中的元素就是整个正则匹配到的子串
re_str = r'\d{3}[A-Z]{2}'
str1 = '你好234KL=skks8920PM坚实的-1a891NB坚实的'
result = re.findall(re_str, str1)
print(result) # ['234KL', '920PM', '891NB']
b.正则中有一个分组 - 匹配成功后将分组匹配到的子串作为列表元素
re_str = r'(\d{3})[A-Z]{2}'
str1 = '你好234KL=skks8920PM坚实的-1a891NB坚实的'
result = re.findall(re_str, str1)
print(result) # ['234', '920', '891']
c.正则中有多个分组 - 匹配成功后每个匹配结果是一个元组,元组中的元素是每个分组匹配到内容,将元组作为列表的元素
re_str = r'(\d{2})-([A-Z]{2})'
str1 = '你好23-KL=skks8920-PM坚实的-1a891NB坚实的'
result = re.findall(re_str, str1)
print(result) # [('23', 'KL'), ('20', 'PM')]
3)finditer(正则表达式,字符串)
获取字符串中所有满足正则表达式的子串;返回一个迭代器,迭代器中的元素是匹配对象
re_str = r'(\d{2})-([A-Z]{2})'
str1 = '你好23-KL=skks8920-PM坚实的-1a891NB坚实的'
result = re.finditer(re_str, str1)
print(result) # <callable_iterator object at 0x108922f50>
print(list(result))
4.字符替换
sub(正则表达式,新字符串,原字符串)
将源字符串中所有满足正则表达式的子串全部替换成新字符串
str1 = '减税降费823世纪东方0kJhjs=139jksd01nkk'
result = re.sub(r'\d+', '+', str1)
print(result) # '减税降费+世纪东方+kJhjs=+jksd+nkk'
5.字符串切割
split(正则表达式,字符串)
将字符串中满足正则表达式的子串作为切割点对字符串进行切割
poem = '床前明月光,疑是地上霜。举头望明月,低头思故乡。'
result = re.split(r'[,。]', poem)
print(result)
三、忽略大小写和多行匹配
1.忽略大小写
在正则表达式的最前面加(?!)
re_str = r'(?i)abc'
print(fullmatch(re_str, 'abc'))
print(fullmatch(re_str, 'ABC'))
print(fullmatch(re_str, 'Abc'))
print(fullmatch(r'abc', 'ABC', flags=IGNORECASE))
2.单行匹配
. 能够匹配换行符的匹配模式,在正则的最前面加(?s)
默认是多行匹配:. 不能匹配换行符
re_str = r'a.+b'
print(fullmatch(re_str, 'a+\nb')) # None
re_str = r'(?s)a.+b'
print(fullmatch(re_str, 'a+\nb')) # <re.Match object; span=(0, 4), match='a+\nb'>
3.符号的转义
在正则中有特殊功能或者特殊意义的符号前加\,让它的功能消失就表示符号本身
在[]外面独立存在有特殊功能的符号,在[]中功能会直接消失
re_str = r'\d\d\.\d\d'
print(fullmatch(re_str, '23.89'))
print(fullmatch(re_str, '23+89')) # None
re_str = r'\(\d\d\)'
print(fullmatch(re_str, '(34)'))
re_str = r'\[\d\d\]'
print(fullmatch(re_str, '[89]'))
re_str = r'\d\+'
print(fullmatch(re_str, '3+'))
# 在[]外面独立存在有特殊功能的符号,在[]中功能会直接消失
re_str = r'[=a+.]123'
print(fullmatch(re_str, 'a123'))
print(fullmatch(re_str, '=123'))
print(fullmatch(re_str, '.123'))
print(fullmatch(re_str, '+123'))
print(fullmatch(re_str, '~123')) # None
re_str = r'[\\d]123'
print(fullmatch(re_str, '\\123'))
print(fullmatch(re_str, 'd123'))
re_str = r'[a\-z]' # [az-]\[-az]
print(fullmatch(re_str, 'a'))
print(fullmatch(re_str, '-'))
print(fullmatch(re_str, 'z'))
print(fullmatch(re_str, 'm')) # None
四、编程思想
面向过程编程:
遇到问题首先想到是用什么样的逻辑和语法写什么代码能够实现这个功能(逻辑,语法)
sum1 = 1
for x in range(1, 11):
sum1 *= x
print(sum1)
sum1 = 1
for x in range(1, 21):
sum1 *= x
print(sum1)
函数式编程
遇到问题首先想到的时候有没有一个已经存在的函数能够完成这个功能,如果有就直接调用这个函数,如果没有就定义一个能够实现这个功能的函数。(函数)
def factorial(n):
sum1 = 1
for x in range(1, n+1):
sum1 *= x
return sum1
print(factorial(10))
print(factorial(20))
面向对象编程
遇到问题首先想到的时候有没有一个对象它有这个功能,没有就去创建这个对象。(类和对象)
class Math:
@staticmethod
def factorial(n):
sum1 = 1
for x in range(1, n + 1):
sum1 *= x
return sum1
@staticmethod
def abs(num):
if num >= 0:
return num
return -num
print(Math.factorial(10))
五、类和对象
1.什么是类什么是对象
类就是拥有相同功能和相同属性的对象的集合(某一类事物的统称,是抽象的概念)
对象就是类的实例(类具体的表现)
2.定义类
语法:
class 类名:
类的说明文档
类的内容(方法、属性)
说明:
1.class - 关键字;固定写法
2.类名 - 程序员自己命名;
要求:a.是标识符 b.不是关键字
规范:a. 采用驼峰式命名,并且首字母大写
b. 见名知义(看到名字大概知道这个类是那种事物的统称)
c. 不能使用系统的函数名、类名或者模块名
3.类的说明文档 - 和函数说明文档的要求一样
4.类的内容 - 类的内容中主要包含类的方法(对象方法、类方法和静态方法)和属性(类属性、对象属性)
方法: 方法就是定义在类中函数
class Housekeeping:
"""
家政类:拥有洗衣服、做饭、打扫的功能
"""
def wash_the_clothes(self):
print('洗衣服')
def cooking(self):
# self = h
print('self:', self)
print('做饭')
def clean(self):
print('打扫')
3.定义对象
语法:
类()
# h就是Housekeeping的对象
h = Housekeeping()
h.cooking()
print('h:', h)