Python正则表达式与面向对象详细教程!表哥花一个月归纳的!
前言 字符串是编程中非常常用的数据结构,对它的操作处理也非常重要。所以学透本知识点,对以后开发过程中对字符串处理,特别是爬虫、对用户输入数据的校验等非常重要。 对于之前从未接触编程的同学来说,"正则表达式"这个名字或许不那么见名知义,总之一看这个名字就让人感觉不太好理解。其实,正则表达式它还有另外一个名字:规则表达式,个人觉得这个"规则表达式"反而更容易被理解。 正则表达式,也即规则表达式,说白了就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,用这个“规则字符串”来表达对字符串的一种过滤逻辑。 常见的场景:对邮箱格式的校验、对手机号的合法性校验、爬虫中核心数据的获取... Python 自1.5版本起增加了re模块,re 模块使 Python 语言拥有全部的正则表达式功能。 compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串,即形参:pattern,来做为它们的第一个参数。 加/X:mmp9972 ??即可获取数十套PDF哦! 正则表达式的思想 正则表达式的设计思想是:用一种描述性的语言来定义一个规则,凡是符合此规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。 我们要学习的就是如何定义这个"规则"。 示例及说明 因为正则表达式也是用字符串表示的,所以我们要首先了解如何用字符来描述字符。
在正则表达式中,如果直接给出字符,就是精确匹配。用d可以匹配一个数字,w可以匹配一个字母或数字,例如: "123d"表示必须是123后跟一位任意数字的,可以匹配:1234、1235,但无法匹配123a "123w"表示必须是123后跟一位任意字母或数字的,可以匹配:1234、1235、123a "ddd"表示3个数字,可以匹配:123、110,但无法匹配abc、12a ·可以匹配任意字符,例如: "abc."表示必须是abc后跟一位任意字符的,可以匹配:abc!、abc1、abc,但无法匹配abc
要匹配变长的字符,在正则表达式中: 用*表示任意个字符(包括0个), 用+表示至少一个字符, 用?表示0个或1个字符, 用{n}表示n个字符, 用{n,m}表示n-m个字符。例如: 上面例子中的"ddd"可以简写为"d{3}"表示3个数字,可以匹配:123、110,但无法匹配abc、12a; "bo*k"可以匹配:bk、bok、book、booooooook等,但无法匹配boak 此处我们先介绍一个函数:re.findall(matten,string,flags) 功能:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。 语法格式:re.findall(matten,flags) 参数说明: matten:正则中的模式字符串。 string:要匹配的字符串。 flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 注意: 后面还会学习另外两个函数match 和 search,现在你只需知道 match 和 search是匹配一次,而 findall 匹配所有。 上面规则用代码验证如下: import re # 设计的正则表达式 pattern = "bo*k" # 待匹配的字符串 content = "bk-bok-book-boooooook-boak" # 用re.findall,在字符串中找到正则表达式所匹配的所有子串,放入一个列表中并返回,如果没有找到匹配的,则返回空列表。 result = re.findall(pattern,content) print(result) 运行结果: ['bk','bok','book','boooooook'] 同理,可以验证: "wo+w"可以匹配:wow、woow、woooooooow等,但无法匹配ww、woaw等; "wo?w"可以匹配:ww、wow等,但无法匹配woow、woooooooow、woaw等; "wo{2}w"可以匹配:woow,但无法匹配ww、wow、woooooooow、woaw等; "wo{2,10}w"可以匹配:woow、woooooooow、,但无法匹配ww、wow、woaw等;
对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。 ^匹配字符串开头,^d表示必须以数字开头。 $匹配字符串行末尾,d$表示必须以数字结束。 A|B可以匹配A或B,所以(H|h)ello可以匹配Hello或者hello。 你可能注意到了,he也可以匹配hello,但是加上^he$就变成了整行匹配,就只能匹配he了。 语法元素 符号含义描述·匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。*匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式+匹配前一个字符1次或多次?匹配一个字符0次或1次^匹配字符串开头。在多行模式中匹配每一行的开头$匹配字符串末尾,在多行模式中匹配每一行的末尾|或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式[ ]字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用反斜杠转义恢复特殊字符的特殊含义。{ }{m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次( )被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。 表示特定含义特殊字符: 符号含义描述w匹配数字字母下划线W匹配非数字字母下划线s匹配任意空白字符,等价于 [ ]S匹配任意非空字符d匹配任意数字,等价于 [0-9]。D匹配任意非数字A匹配字符串开始z匹配字符串结束Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。G匹配最后匹配完成的位置。匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。B匹配非单词边界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。,匹配一个换行符。匹配一个制表符等 re模块 Python 自1.5版本起增加了re模块,re模块使 Python 语言拥有全部的正则表达式功能。 在设计规则表达式时,要特别注意字符转义。由于Python的字符串本身也用转义,所以要特别注意: # Python的字符串 content = 'ABC-001' # 对应的正则表达式字符串变成: # 'ABC-001' 因此我们强烈建议使用Python的r前缀,就不用考虑转义的问题了: # Python的字符串 content = r'ABC-001' # 对应的正则表达式字符串不变: # 'ABC-001'
re.match 方法尝试从字符串的起始位置去匹配一个模式,判断起始位置是否能匹配,如果匹配成功,返回一个Match对象,否则返回None。 函数语法:re.match(pattern,flags) 函数参数说明: 参数参数说明pattern匹配的正则表达式string要匹配的字符串flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 【示例】 re.match 方法是从起始位置去匹配的。注意区分下面两种匹配结果: # 设计的正则表达式,3个数字 patten = r"d{3}" # 两个待匹配的测试内容 content = "010-123456789" content2 = "测试不在起始位置:010-123456789" # 调用 re.match,获取匹配结果 result = re.match(patten,content) result2 = re.match(patten,content2) # 打印匹配结果 print(r"result = {}".format(result)) print(r"result2 = {}".format(result2)) 运行结果: result =
split 方法按照能够匹配的子串将字符串分割后返回列表。 函数语法: re.split(pattern,string[,maxsplit=0,flags=0]) 函数参数说明: 参数参数说明pattern匹配的正则表达式string要匹配的字符串maxsplit分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 用正则表达式切分字符串比用固定的字符更灵活,常规切分代码: content = "a b c d e" print(content.split(" ")) 打印切分结果: ['a','b','','c','d','e'] 缺陷是无法用连续的空格去切分,而正则表达式可以灵活切分: content = "a b c d e" # 用一个空格或连续空格 pattern = r"s+" print(re.split(pattern,content)) 打印切分结果: ['a','e'] 如果待分割的字符串中含有了其他字符"a,b; c d e",要得到['a','e'],也是可以的: content = "a,b; c d e" # 用一个空格或连续空格 pattern = r"[s,;]+" print(re.split(pattern,'e']
Python 的re模块提供了re.sub用于替换字符串中的匹配项。 语法:re.sub(pattern,repl,count=0) 参数说明: 参数参数说明pattern匹配的正则表达式repl替换的字符串,也可为一个函数。string要被查找替换的原始字符串。count模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。 示例如下: phone = "400-666-1234 # 这是一个电话号码" # 删除注释 num = re.sub(r'#.*$',"",phone) print("电话号码 : ",num) # 移除非数字的内容 num = re.sub(r'D',num) 运行结果: 电话号码 : 400-666-1234 电话号码 : 4006661234
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。 re.finditer(pattern,flags=0) 此处参数和其他意义一样,不再赘述。
除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。其中,被括起来的正则表达式将作为一个分组。 ^(d{3,4})-(d{3,8})$分别定义了两个组:(d{3,4})、(d{3,8}),可以直接从匹配的字符串中提取出区号和本地号码: # 设计正则表达式 pattern = r"(d{3,4})-(d{6,8})" # 待匹配的内容 content = "0755-123456" # 获取匹配结果 result = re.match(pattern,content) print(result) print(result.group()) print("第0组:" + result.group(0)) print("第1组:" + result.group(1)) print("第2组:" + result.group(2)) 运行结果:
一旦正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。注意到group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串。 在上面,当匹配成功时返回一个 Match 对象,其中Match 对象包含的信息: group([group1,…])方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用group()或 group(0); start([group])方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0; end([group])方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0; span([group])方法返回 (start(group),end(group))。
当我们在Python中使用正则表达式时,re模块内部会干两件事情: 1.编译正则表达式,如果正则表达式合法,编译后生成Pattern对象。如果正则表达式的字符串本身不合法,会报错; 2.用编译后的正则表达式去匹配字符串。 如果一个正则表达式要重复使用成百上千次,则出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配。 compile函数用于编译正则表达式,生成一个正则表达式Pattern对象,该对象有提供match()和 search() 这两个函数使用。 语法格式为:re.compile(pattern[,flags]) 参数: 参数参数说明pattern匹配的正则表达式flags标志位,可选,表示匹配模式,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 flags 参数可取的值 flags 参数可取的值取值说明re.I忽略大小写re.L表示特殊字符集 w,W,B,s,S 依赖于当前环境re.M多行模式re.S即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)re.U表示特殊字符集 w,d,D,S 依赖于 Unicode 字符属性数据库re.X为了增加可读性,忽略空格和' # '后面的注释 # 设计正则表达式 pattern = r"(d{3,8})" # 编译正则表达式 rex_phone = re.compile(pattern) # 待匹配的内容 content = "0755-123123" # 获取匹配结果 result = rex_phone.match(content) print(result) print(result.group()) print("第0组:" + result.group(0)) print("第1组:" + result.group(1)) print("第2组:" + result.group(2))
re.search 扫描整个字符串并返回第一个成功的匹配。 函数语法:re.search(pattern,flags=0) 注意:匹配成功re.search方法返回一个匹配的对象,否则返回None。 re.match与re.search的区别 re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,从开始去找,直到找到一个匹配。如果直到结束还没找到匹配的,才返回None。 小结 正则表达式,也即规则表达式,说白了就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,用这个“规则字符串”来表达对字符串的一种过滤逻辑。 正则表达式的内容非常丰富,我们只是学习了其中最基础、最为常用的知识点,而这些满足日常开发也绰绰有余了。 接下来就是面向对象了! ★ 目录 ★ 01 类、对象定义及使用 02 属性和方法 03 构造方法 04 封装、继承、多态 01. 类、对象定义及使用 定义类语法 class 类名(父类): 代码块 注意:()可有可无 eg: class Person: #这是一个类 创建对象(实例)语法 对象名=类名() 注意:Java语言在实例化对象是,采用new关键字,而Python语言不需要。 eg: person=Person() isinstance()语法 isinstance()是检测一个对象是否是一个类的实例,语法格式: isinstance(对象,类),结果返回True和False eg: isinstance(person,Person),结果为True 02.属性和方法 属性 属性:分为类属性和对象属性 属性修饰符:私有属性、公共属性 类属性 class Person: name="张三" #name是类属性 对象属性 p1=Person() p1.name="张三" #name是对象属性 类属性和对象属性的区别? 类属性直接通过类名就可以调用,比如: Person.name 对象属性必须通过对象名调用,比如: person.name 公共属性 没有任何修饰符,该类型的属性可以被任意一个对象所调用,比如: name="张三" 私有属性 私有属性,不能通过对象调用,也不能通过类名调用,只能在本类中调用,类似Java语言中的private,如果想要在外部调用,则需提供get和set方法,私有属性通过双下划线修饰__ eg: __name="张三" #这是一个私有属性 方法 方法分类:对象方法、类方法、静态方法 对象方法 定义在类中的函数被称为方法,所有的实例都可以访问 注意:对象方法,必须默认传递一个参数self,类似java中的this关键字 调用:只能通过对象调用 eg: class Person: def eat(self): 代码块 #调用 person=Person() person.eat() 类方法 被@classmethod修饰的方法,被称为类方法 参数:cls 调用:可以通过类调用 eg: @classmethod def sleep(cls): print("睡觉") #调用 Person.sleep() 静态方法 被@staticmethod修饰的方法,被称为静态方法 参数:无参数 调用:可以通过类和对象调用 @staticmethod def playDD(): print("打豆豆") #调用 Person.playDD() #类名调用 person.playDD() #对象调用 03.构造方法 构造方法 构造方法是以双下划线__开头,双下划线__结尾,方法名叫init,构造方法不需要自己调用,在实体化对象时调用,和Java中的构造方法一样,语法格式: def __init__(self,参数): 代码块 eg: def __init__(self,name,age): self.__name=name self.__age=age 04.封装 封装 封装,是给类中的属性提供get、set方法,语法格式: def set方法(self): 代码块 def get方法(self): 代码块 eg: def setName(self,name): self.__name=name def getName(self): return self.__name get、set装饰器 get方法装饰器:@property set方法装饰器:@属性名.setter 调用:直接通过对象.属性名即可 注意:get方法修饰器必须写到set方法修饰器前面 eg: @property def name(self): return self.__name @name.setter def name(self,name): self.__name=name 06.继承 继承语法 class 子类(父类1,父类2): 通过语法格式可以看出Python语言支持多继承,Java语言只支持单继承 issubclass() issubclass()方法作用: 检测一个类是否是另外一个类的子类 语法: issubclass(子类,父类) 方法重写 像Java语言一样,Python语言也同样支持方法的重写override 多继承 查看一个类的继承关系使用: 类名.__bases__属性 多继承特点: 一层一层获取,先找自己的类中,再从继承关系中找 07.多态 多态 多态的概念,和Java中的概念是一样的。可以看下面的例子理解,或者看视频教程 class Person: def __init__(self,name): self.__name=name @property def name(self): return self.__name @name.setter def name(self,name): self.__name=name class Boy: def __init__(self,name): self.__name=name class Girl: pass def eat(obj): print("%s正在吃饭"%obj.name) p=Person("战三") b=Boy("小孩子") g=Girl() eat(g),参数p、b都没有问题,但是g就会有问题 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |