继承和重写
-
继承 - 可以在python中最大程度地减少代码量
-
被继承的类叫做父类/基类/超类,继承的类叫子类/衍生类/派生类
-
子类可继承父类的属性和方法
-
一个子类可以继承多个父类,也可间接继承
# 隔壁老王是煎饼果子名人,他有一天干不动了,但是不想让探索几十年秘籍流失。 # 所以隔壁老王将秘籍传给了他的大儿子王二麻子 class Father: def __init__(self, name='隔壁老王', kungfu='《煎饼果子宝典》'): self.name = name self.kungfu = kungfu def cook(self): return f'{self.name}能够根据{self.kungfu}做出美味的煎饼果子' F1 = Father() print(F1.cook()) # 继承语法: 类名后面添加小括号,小括号中写被继承的父类的类名 class Son(Father): # 子类还可以拥有自己的属性,但是子类一旦拥有了自己的属性,它将不再继承父类属性 def __init__(self, age): # 子类的超类的初始化属性 -- 方法1 # super(Son, self).__init__() # 直接将父类的属性拿过来,使用self传值 Father.__init__(self) self.age = age # 子类虽然继承了父类,但是子类还可以拥有自己的方法。 # 王二麻子还想去学校学习新式的煎饼果子.....王二麻子学成归来 def newCook(self, book): return f'{self.name}学成归来,能够根据{book}制作出美味的新式煎饼果子' # 重写父类的方法 def cook(self): return f'{self.name}根据《煎饼果子宝典》和《新式煎饼果子秘籍》改良出了更好吃的煎饼果子' # 子类重写父类方法后还想再使用父类的方法 def oldCook(self): return super(Son, self).cook() S1 = Son(30) S1.name = '王二麻子' print(S1.cook()) S1.newCook('《新式煎饼果子秘籍》') print(S1.oldCook()) # 王二麻子将父亲的煎饼果子发扬光大,年纪轻轻我的月工资就达到了3200,走向了人生巅峰。 # 王二麻子退休后又想将自己的一身技能传给儿子。
继承练习
# 定义一个类,能够计算一条线段的长度。再定义一个圆类,这个圆类能够计算圆心到原点的距离
class Line:
def __init__(self, point1, point2):
self.point1 = point1
self.point2 = point2
def line_length(self):
if self.point1[0] == self.point2[0]:
return f'线段的长度为{abs(self.point1[1] - self.point2[1])}'
elif self.point1[1] == self.point2[1]:
return f'线段的长度为{abs(self.point1[0] - self.point2[0])}'
else:
result = ((self.point1[0] - self.point2[0]) ** 2 + (self.point1[1] - self.point2[1]) ** 2) ** 0.5
return result
L1 = Line((1, 6), (2, 5))
print(L1.line_length())
class Circle(Line):
def __init__(self, point3):
self.point3 = point3
def distance(self):
result1 = (abs(self.point3[0] - 0) ** 2 + abs(self.point3[1] - 0) ** 2) ** 0.5
return f'圆心到原点的距离为{result1}'
C1 = Circle((3, 9))
print(C1.distance())
正则表达式
-
正则表达式 - 用一系列特殊符号从字符串中匹配内容
-
正则表达式独立于其他语言的语法
-
所有语言中的正则表达式语法相同,只是使用方式不一样
# 匹配语法fullmatch # fullmatch(正则表达式, 字符串): 判断字符串是否完全符合正则表达式的内容 # 若fullmatch结果成立,则返回一个对象,不成立则返回None
-
匹配类符号
# .(点): 可以匹配任意一个符号 # \d: 匹配0-9数字 # \D: 匹配非数字 # \s: 匹配空白符号(空格, \n, \t, \v等) # \S: 匹配非空白符号 # \w: 匹配数字、字母、下划线、中文、朝鲜语 # [a-z]: 表示匹配小写字母中的任意一个 # [A-Z]: 表示匹配大写字母中的任意一个 # [0-9]: 表示匹配0-9中的任意一个数字 # [\u4e00-\u9fa5]: 匹配任意一个汉子 # [a-zA-Z]: 匹配任意一个字母 # [0-9a-zA-Z\u4e00-\u9fa5]: 匹配数字、字母和汉字中的任意一个 # [012345678-]:匹配0-8和-中的任意一个符号 # [^字符集]: 匹配不在字符集中的元素 # 字符集规则: -连接的是范围,-左边必须小于右边,-不能出现在字符集开头或结尾,不然表示-自己
-
findall打印匹配结果
# findall(正则表达式, 字符串): # 方法一: 从字符串中按照正则表达式的规则匹配所有可能,并将每一个结果放到列表中 # 方法二: 如果正则表达式中出现了分组,只会获取符合正则表达式结果中符合分组中规则的结果 str1 = 'a1b3d45f6j7' # 从这个字符串中将所有的数字匹配出,每个结果为一位数字 re_str = '[0-9]' print(re.findall(re_str, str1))
-
单次、多次匹配,贪婪与非贪婪
# 1. ?: 匹配0次或1次 # 2. +: 匹配一次或多次 # 3. *: 匹配任意次数 # 4. {M,N} # {M}: 匹配M次 # {N}: 匹配N次 # {M,N}:最少匹配M次,最多匹配N次 # {M,}: 最少匹配M次 # {,N}: 最多匹配N次,最少匹配0次 import re # 1. ?: 匹配0次或1次 re_str = 'a\d?' str1 = 'a' print(re.fullmatch(re_str, str1)) # 输出结果为<re.Match object; span=(0, 1), match='a'> # 2. +: 匹配一次或多次 str1 = 'a1b3d45f6j7' # 从这个字符串中将所有的数字匹配出,每个结果为一位数字 re_str = '[0-9]+' # re_str = '\d+' print(re.findall(re_str, str1)) # 输出结果为['1', '3', '45', '6', '7'] # 3. *: 匹配任意次数 str1 = 'a1b3d45f6j7' print(re.findall('\d*', str1)) print(re.findall('a\d*', str1)) # 输出结果为['', '1', '', '3', '', '45', '', '6', '', '7', ''] # 输出结果为['a1'] # 4. {M,N} # {M}: 匹配M次 # {N}: 匹配N次 # {M,N}: 最少匹配M次,最多匹配N次 # {M,}: 最少匹配M次 # {,N}: 最多匹配N次,最少匹配0次 # 从这个字符串中将所有的数字匹配出,每个结果为一位数字 re_str = '[0-9]+' re_str = '\d{1,}' print(re.findall(re_str, str1)) # 输出结果为['1', '3', '45', '6', '7'] # 贪婪和非贪婪 # 默认所有次数不确定的匹配都是贪婪的,会一次获取尽可能多的元素: 比如: +,*,{,N},{M,}等 # 非贪婪就是一次匹配取最短长度的结果,在非贪婪涉及的符号的基础上添加一个?即可, +?,*?,{,N}等 str1 = 'abcabcabc' re_str = 'a.+c' print(re.findall(re_str, str1)) # 输出结果为['abcabcabc'] re_str = 'a.+?c' print(re.findall(re_str, str1)) # 输出结果为['abc', 'abc', 'abc'] # 将'hghjkae中i90b=oiuyghjv'中的"ae中i9"取出来 str2 = 'hghjkae中i90b=oiuyghjv' re_str = 'a.+9' print(re.findall(re_str, str2)) # 输出结果为['ae中i9']
-
分支和分组
import re # 分支: | str1 = 'abcabd' # 分别匹配出"abc"和"abd" # re_str = '[ab.]+' re_str = '[aba-z]{3}' print(re.findall(re_str, str1)) # 输出结果为['abc', 'abd'] # .通配符放到[]中特殊意义消失 re_str = 'abc|abd' print(re.findall(re_str, str1)) # 输出结果为['abc', 'abd'] # 分组: () # 1. 能够将同类项提出来 # 2. 能够将分组中的结果重复 str1 = 'abcabd' re_str = '(ab(c|d))' print(re.findall(re_str, str1)) # 输出结果为[('abc', 'c'), ('abd', 'd')] str2 = '1234==12341234' re_str = r'(\d{4})(=)\2\1\1' # 如果字符串后面再次出现过前面匹配过的结果,可以将前面的结果使用分组包围起来 # 结合\N(N是数字,代表第N个分组)的语法,可以将前面第N个分组的结果重复使用 print(re.fullmatch(re_str, str2)) # 输出结果为<re.Match object; span=(0, 14), match='1234==12341234'> # '(ab(c|d))(abc)' -> (ab(c|d))是第一个分组,(c|d)第二个分组,(abc)第三个分组 # 正则表达式不是转义字符,在写正则表达式时,在正则表达式前面添加r或者R。
正则表达式
-
fullmatch、findall、split、search、match
# fullmatch: 查看整个字符串是否符合正则表达式 (可能会出现空值None) # findall: # 方法一: 将字符串中所有符合正则表达式的结果匹配出来 # 方法二: 如果正则表达式中出现分组,会先按照表达式匹配出结果,再将符合分组中正则表达式的结果提取 # split: 按正则表达式规则切割字符串 # sub: 将符合正则表达式的结果替换为新字符串 # search: 找出字符串中第一个符合正则表达式的结果 (可能出现空值None) # match: 查看字符串开头是否符合正则表达式规则 (可能出空值None) import re str1 = 'a, b.c' re_str = 'a,' print(re.match(re_str, str1)) # 输出结果为<re.Match object; span=(0, 2), match='a,'> re_str = '[a-z]' print(re.search(re_str, str1)) # 输出结果为<re.Match object; span=(0, 1), match='a'> re_str = '[,.]' print(re.split(re_str, str1)) # 输出结果为['a', ' b', 'c'] # re.sub(正则, newStr, oldStr) print(re.sub('[,.]', '', str1)) # 输出结果为a bc # 常用: findall、split、sub # 不常用: match、search、fullmatch
-
练习
# 匹配平年正确的日期格式 # 2-29(错)\4-31(错) # 1-31\1-30(正确) # 13578、10、12 有 31天 # 2 有 28天 # 469、11 有 30天 import re list1 = ['2-28', '2-29', '1-31', '1-32', '4-30', '4-31', '12-31'] re_str = '([13578]|1[02])-([1-9]|[12]\d|3[01])' re_str1 = '2-([1-9]|1\d|2[0-8])' re_str2 = '[469]|11-([1-9]|[12]\d|30)' new_str = fr'{re_str}|{re_str1}|{re_str2}' for i in list1: if re.fullmatch(new_str, i) != None: print(i, True) else: print(i, False)