正则和面向对象
一、正则语法
1.贪婪和非贪婪
当匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种。
贪婪:在能匹配成功的前提下,次数尽可能多的匹配(越多越好)。默认情况下都是贪婪
非贪婪:再能匹配成功的前提下,次数尽肯能少的匹配(越少越好)。在不确定的匹配次数后加?就是非贪婪(*?, +?, ??, {M,N}? , {M,}?, {,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.检测符号
检测类的符号只做字符的检测不会进行匹配。
- \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']
- ^ - 检测是否是字符串开头
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']
- $ - 检测是否是字符串结尾
re_str = r'\d{3}$'
print(findall(re_str, '7829ahs345ksdj897四季花海345jsks345, 345, 894集 899 288 三等奖345'))
# ['345']
3.分支 - |
| - 在正则中表示或者
正则表达式1|正则表达式2|正则表达式3|… - 让字符串先和第一个正则进行匹配如果失败再和第二个正则匹配,以此类推…
练习:写一个正则能够匹配3个数字或者3个字母
re_str = r'\d{3}|[a-zA-Z]{3}'
print(fullmatch(re_str, '234'))
print(fullmatch(re_str, 'jsK'))
练习:写一个正则能匹配的字符串是: abc后面是三个数字或者两个大写字母
re_str = r'abc\d{3}|abc[A-Z]{2}'
print(fullmatch(re_str, 'abc342'))
print(fullmatch(re_str, 'abcKL'))
4.分组 - ()
- 把正则的部分内容看成一个整体,进行操作
re_str = r'abc(\d{3}|[A-Z]{2})'
print(fullmatch(re_str, 'abc234'))
练习: 写一个正则能够匹配一个字符串是两个数字三个字母这种结构不断重复的字符串
re_str = r'(\d{2}[a-zA-Z]{3})+'
print(fullmatch(re_str, '67hsj89klo89jju90kkl'))
print(fullmatch(re_str, '89jsk90uwu'))
- 分组和\N匹配使用来控制匹配内容重复
re_str = r'abc(\d{2})=\1'
print(fullmatch(re_str, 'abc78=78'))
# re_str = r'abc\1(\d{2})' # re.error: invalid group reference 1 at position 4
# print(fullmatch(re_str, 'abc78=78'))
# re_str = r'abc(\d{2})=\2' # re.error: invalid group reference 2 at position 12
# print(fullmatch(re_str, 'abc78=78'))
re_str = r'([a-z]{3})(\d{2})\2\1\1'
print(fullmatch(re_str, 'xyz3434xyzxyz'))
re_str = r'([a-z]{3})(\d{2})\1{3}'
print(fullmatch(re_str, 'mna99mnamnamna'))
re_str = r'(a(\d{2}))\1=\2'
print(fullmatch(re_str, 'a34a34=34'))
二、re模块
先导入re模块 - import re
1.compile(正则表达式) - 编译正则表达式创建一个正则表达式对象
re_obj = re.compile(r'\d{3}')
re.fullmatch(正则表达式, 字符串)
正则对象.fullmatch(字符串)
print(re_obj.fullmatch('799'))
# <re.Match object; span=(0, 3), match='799'>
2.匹配
- fullmatch(正则表达式, 字符串) - 完全匹配,查看整个字符串是否和正则表达式匹配;匹配成功返回匹配对象,失败返回None
- 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'))
# <re.Match object; span=(0, 3), match='789'>
- 匹配对象(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'>
获取匹配到的字符串
匹配对象.group() - 获取整个正则匹配到的结果
匹配对象.group(N) - 获取正则中第N个分组匹配到的结果
print(result.group()) # 234kl
print(result.group(1)) # 234
print(result.group(2)) # kl
获取匹配到的字符串在原字符串中的位置
print(result.span()) # (0, 5)
print(result.span(1)) # (0, 3)
print(result.span(2)) # (3, 5)
获取原字符串
print(result.string) # 234kl数据库是否
3.查找
- 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'>
- 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')]
- 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))
# [<re.Match object; span=(2, 7), match='23-KL'>, <re.Match object; span=(14, 19), match='20-PM'>]
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)
# ['床前明月光', '疑是地上霜', '举头望明月', '低头思故乡', '']
三、忽略大小写和多行匹配
导入模块
from re import fullmatch, IGNORECASE
1.忽略大小写:在正则表达式的最前面加(?i)
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.Match object; span=(0, 4), match='(34)'>
re_str = r'\[\d\d\]'
print(fullmatch(re_str, '[89]'))
# <re.Match object; span=(0, 4), match='[89]'>
re_str = r'\d\+'
print(fullmatch(re_str, '3+'))
# <re.Match object; span=(0, 2), match='3+'>
- 在[]外面独立存在有特殊功能的符号,在[]中功能会直接消失
re_str = r'[=a+.]123'
print(fullmatch(re_str, 'a123'))
# <re.Match object; span=(0, 4), match='a123'>
print(fullmatch(re_str, '=123'))
# <re.Match object; span=(0, 4), match='=123'>
print(fullmatch(re_str, '.123'))
# <re.Match object; span=(0, 4), match='.123'>
print(fullmatch(re_str, '+123'))
# <re.Match object; span=(0, 4), match='+123'>
print(fullmatch(re_str, '~123')) # None
re_str = r'[\\d]123'
print(fullmatch(re_str, '\\123'))
# <re.Match object; span=(0, 4), match='\\123'>
print(fullmatch(re_str, 'd123'))
# <re.Match object; span=(0, 4), match='d123'>
re_str = r'[a\-z]' # [az-]\[-az]
print(fullmatch(re_str, 'a'))
# <re.Match object; span=(0, 1), match='a'>
print(fullmatch(re_str, '-'))
# <re.Match object; span=(0, 1), match='-'>
print(fullmatch(re_str, 'z'))
# <re.Match object; span=(0, 1), match='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 类名:
类的说明文档
类的内容(方法、属性)
说明:
- class - 关键字;固定写法
- 类名 - 程序员自己命名
要求:是标识符;不是关键字
规范:采用驼峰式命名,并且首字母大写;见名知义;不能使用系统的函数名、类名和模块名 - 类的说明文档 - 和函数说明问道要求一样
- 类的内容 - 类的内容主要包含类的方法(对象方法、类方法和静态方法)和属性(类属性、对象属性)