day18笔记 错误和异常 正则表达式

本文深入探讨Python中的异常处理机制,包括错误、异常的概念,常见异常类型及处理方式,如try-except-finally结构。同时,详细讲解正则表达式的使用,包括单字符、多字符匹配,贪婪与非贪婪匹配,边界匹配等,以及在Python中的应用案例。
摘要由CSDN通过智能技术生成

一、异常和错误

1.概念

Python有两种错误很容易辨认:语法错误和异常

​ Python 的语法错误或者称之为解析错误,是初学者经常碰到的,比如缺少冒号等

​ 在程序运行过程中,总会遇到各种各样的错误,有的错误是程序编写有问题造成的,这种错误我们通常称之为bug,bug是必须修复的;有的错误是用户输入造成的,这种错误可以通过检查用户输入来做相应的处理;还有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了,这类错误被称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出

#1.错误
#特点:直接报错【语法错误,编码规范】
#  num = 10
# 3abc = "hello"

#2.异常
#特点:当代码运行的时候会报错
try:
 list1 = [2, 4, 5, 5]
 print(list1[4])
except:
 print("出现了异常")

print("over")

#问题:如果代码中出现异常,但是未被处理,则程序会终止在出现异常处
#解决方案:如果出现异常,让程序继续执行
2.常见异常【面试题】

AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

#1.ValueError
#num = int(input("请输入:"))
#ValueError: invalid literal for int() with base 10: 'abc'

#2.NameError
#print(num)
#NameError: name 'num' is not defined

#3.AttributeError
class Person():
 __slots__ = ("name",)
p = Person()
# p.age = 10
#AttributeError: 'Person' object has no attribute 'age'

#print("abc".reverse())
#AttributeError: 'str' object has no attribute 'reverse'

#4.KeyError
# dict1 = {"a":10}
# print(dict1["b"])
#KeyError: 'b'

#5.UnboundLocalError
# a = 1
# def func():
#     a += 1
# func()
#UnboundLocalError: local variable 'a' referenced before assignment

#6.FileNotFoundError
#f = open(r"a.txt","w",encoding="utf-8888")
#FileNotFoundError: [Errno 2] No such file or directory: 'a.txt'
#LookupError: unknown encoding: utf-8888

#7.ModuleNotFoundError
#import aaa
#ModuleNotFoundError: No module named 'aaa'

#8.KeyboardInterrupt:当手动结束程序
# while True:
#     pass
3.异常处理方式

处理异常的本质:没有从根本上解决问题【修改代码】,只是将异常忽略,可以让后面的代码继续执行

3.1try-except-finally/else捕获【常用】
"""
语法:
 try:
     语句1
 except 错误标识码  as 变量:
     语句2
 except 错误标识码  as 变量:
     语句3
 ....
 else/finally:
     语句n

说明:
 a.try块中的语句被称为代码监测区,将可能存在异常的代码书写在这里
 b.如果try中的代码出现了异常,会匹配相应的except语句,
   注意:此处的except并不是真正的将异常处理了,只是做了一个拦截 ,可以让后面的代码继续执行
 c.else和finally语句可以根据具体的需求选择性的省略
"""

#1.try-except    ******
"""
try:
 #注意1:将可能存在异常的代码书写在try块中检测起来
 num = int(input("请输入一个数字:"))
#注意2:e只是一个变量名,可以是任意的标识符,在编程语言中,异常为Exception,所以惯用e
#注意3:e的类型是<class 'ValueError'>,e就是一个对象,相当于e = ValueError()
except ValueError as e:
 print(e,type(e))
#注意4:当try中的代码出现异常,则执行相应的except语句
# 【如果没有匹配到相应的except,则异常还未被处理】,
# 如果没有异常,则直接跳过except语句

#注意5:打印e获取的结果为字符串,因为异常类中已经重写了__str__函数

"""

#2.try-except-except....     ******
"""
#注意6:如果有多个except,至多只会执行一个,从上往下依次匹配,出现在最上面的最先被匹配
#注意7:不管try中有几个异常,最终都只会匹配一个except
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
#注意8:所有异常的父类是BaseException【Exception】,
# 如果except中出现了父类,而且父类出现在最上面,会匹配所有的异常
except ValueError as e:
 print("value:",e)
except Exception as e:
 print("父类:",e)
except IndexError as e:
 print("index:",e)

print("over")
"""

#3.try-except 父类
"""
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
except Exception as e:
 print("父类:",e)

print("over")
"""


#4.try-except,省略类型
#说明:也可以匹配所有类型的异常,但是对于异常的描述缺失
"""
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
except:
 print("出现了异常")

print("over")

"""

#5.try-except (错误码1,错误码2.。。。)
#说明:匹配指定类型的异常
"""
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
except (IndexError,ValueError,AttributeError):
 print("出现了异常~~")

print("over")
"""

#6.try-except-else
#注意9:只有当try中的代码没有异常时,else才会被执行
"""
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
except ValueError as e:
 print(e)
except IndexError as e:
 print(e)
else:
 print("else被执行了")

print("over")

"""

#7.try-except-finally
#注意10:不管try中的代码是否存在异常,finally语句都会被执行
#使用场景:定义清理行为,表示无论在任何情况下都会执行的清理行为,比如:关闭文件,关闭数据库等
"""
try:
 num = int(input("请输入一个数字:"))
 list1 = [2,5,56]
 print("列表中的元素:",list1[num])
except ValueError as e:
 print(e)
except IndexError as e:
 print(e)
finally:
 print("finally被执行了")

print("over")
"""

#【面试题】当try-except-finally语句出现在函数中,
# 如果try或者except语句中出现return,finally还是会正常执行
"""
注意:
 a.如果有异常:try-except-finally
 b.如果没有异常:try-finally
"""
"""
def func():
 try:
     num = int(input("请输入一个数字:"))
     list1 = [2, 5, 56]
     print("列表中的元素:", list1[num])
     return
 except ValueError as e:
     print(e)
     return
 except IndexError as e:
     print(e)
 finally:
     print("finally被执行了")
func()
"""

#8.如果函数中的代码可能存在异常,可以在函数中直接处理,也可以处理函数的调用
#方式一
"""
def func():
 try:
     num = int(input("请输入一个数字:"))
     list1 = [2, 5, 56]
     print("列表中的元素:", list1[num])
 except ValueError as e:
     print(e)    
 except IndexError as e:
     print(e)
func()
"""

#方式二
def func():
 num = int(input("请输入一个数字:"))
 list1 = [2, 5, 56]
 print("列表中的元素:", list1[num])

try:
 func()
except ValueError as e:
 print(e)
except IndexError as e:
 print(e)
3.2raise抛出
#异常对象出现的形式
#1.根据具体的问题出现:是一种可能性
try:
 num = int(input("输入:"))
except ValueError as e:
 print(e)

#2.可以手动创建一个异常的对象:百分百出现
try:
 raise ValueError("hello hello")
except ValueError as e:
 print(e)
#使用场景:一般用在自定义异常中
3.3assert断言
#assert:断言,预言

def func(num1,num2):
 #断言
 #预测成功,则获取结果,预测失败,则打印预测的信息
 #换句话说,用来测试一个表达式是否成立,如果返回值为假,就会触发一个新的异常,为AssertionError
 assert num2 != 0,"除数或者分母不能为0"
 return  num1 / num2

print(func(10,0))
4.嵌套定义
"""
try:
 语句
except:
 语句
finally:
 try:
     语句
 except:
     语句
"""
print("我要去拉萨")

try:
 print("我准备坐飞机过去")
 raise Exception("由于大雾,飞机不能起飞")
 print("到拉萨了,拉萨真漂亮")
except Exception as e:
 print(e)
 try:
     print("我准备坐火车过去")
     raise Exception("由于修路,火车停止")
     print("到拉萨了,拉萨真漂亮")
 except Exception as e:
     print(e)
     print("我骑自行车过去")
     print("到拉萨了,拉萨真漂亮")
5.自定义异常
#【面试题:书写自定义异常】

#1.自定义一个类,继承自BaseException或者Exception
class MyException(BaseException):
 #2.书写构造函数,定义一个实例属性,表示当异常出现时异常的描述信息
 def __init__(self,msg):
     #3.继承父类的异常机制【调用父类的构造函数】
     super(MyException,self).__init__()
     self.msg = msg

 #4.重写__str__,返回异常的描述信息
 def __str__(self):
     return self.msg

 #5.定义一个实例函数,如果出现了异常,则需要手动处理
 def handle(self):
     #注意:在实际项目开发中,在此书是需要实际进行处理异常的操作
     print("处理了异常")

try:
 raise MyException("出现了异常")
except MyException as e:
 print(e)

 #调用处理异常的函数
 e.handle()

#使用场景:使用系统的类解决不了生活中问题,则需要自定义异常

二、正则表达式

1.概述

正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。

  • 搜索模式可用于文本搜索和文本替换。
  • 正则表达式是由一个字符序列形成的搜索模式。
  • 当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容。
  • 正则表达式可以是一个简单的字符,或一个更复杂的模式。
  • 正则表达式可用于所有文本搜索和文本替换的操作

使用场景:

  • 用于验证邮箱格式 手机号格式 密码格式等
  • 爬虫时,使用正则抓取网页中指定内容

而在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行

Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。

re 模块使 Python 语言拥有全部的正则表达式功能

re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数

2.案例
#封装函数,检测qq号的合法性
"""
分析:
 1.纯数字
 2.长度为5~11
 3.开头不能为0
"""

import  re

def isqq1(qq):
 #假设法
 result = True

 if qq.isdigit():

     if len(qq) <= 11 and len(qq) >= 5:
         if qq[0] == "0":
             result = False
     else:
         result = False
 else:
     result = False

 return result


def isqq2(qq):
 # 假设法
 result = True

 try:
     num = int(qq)

     if len(qq) <= 11 and len(qq) >= 5:
         if qq[0] == "0":   #startswith()
             result = False
     else:
         result = False

 except ValueError as e:
     result = False

 return result

if __name__ == "__main__":
 print(isqq1("244564774567588"))
 print(isqq2("2445647745688568"))

 #使用正则表达式判断扣扣好的合法性
 print(re.match(r"^[1-9]\d{4,10}$","24456566"))
 print(re.match(r"^[1-9][0-9]{4,10}$", "24456566"))
3.使用
3.1单字符匹配
#单字符匹配
"""
.                匹配除换行符以外的任意字符

[0123456789]     []是字符集合,表示匹配方括号中所包含的任意一个字符
[0-9]            匹配任意数字,类似[0123456789]
\d               匹配数字,效果同[0-9]


[good]           匹配good中任意一个字符
[a-z]            匹配任意小写字母
[A-Z]            匹配任意大写字母
[0-9a-zA-Z]      匹配任意的数字和字母

[0-9a-zA-Z_]     匹配任意的数字、字母和下划线
\w               匹配数字,字母和下划线,效果同[0-9a-zA-Z_]


[^good]          匹配除了good这几个字母以外的所有字符,中括号里的^称为脱字符,表示不匹配集合中的字符

[^0-9]           匹配所有的非数字字符
\D               匹配非数字字符,效果同[^0-9]


\W               匹配非数字,字母和下划线,效果同[^0-9a-zA-Z_]

\s               匹配任意的空白符(空格,回车,换行,制表,换页),效果同[ \r\n\t\f]
\S               匹配任意的非空白符,效果同[^ \f\n\r\t]
"""

"""
[]    不管其中书写了多少个字符,都只能匹配其中的一位

-     连接符,如1-9表示123456789,如果表示连续的数字或者字母都可以使用-表示 
      举例:[358]表示3,5,8,[3-8]表示345678
      
[^xxx]  脱字符,^写在[]中表示否定,直接写在正则字符串中表示匹配开头

\     转义字符,字符可以是d和D,s和S,w和W,都表示单个字符的匹配

.     匹配除了换行符以外的任意字符
"""
import re

#re模块中常用的函数有:compile【编译】,match【匹配】,
# search/findall【搜索】,sub【替换】,split【分隔】等

#方式一
#re.xxxx(pattern,string,flags),pattern表示正则匹配规则
r0 = re.match(r"[a-z]","y")
print(r0)

#方式二
"""
result = re.compile(pattern)
pattern.xxxx(string)
"""
pattern = re.compile(r"[a-z]")
r1 = pattern.match("y")
print(r1)

#注意:match(),如果匹配上,则返回对象,如果匹配不上,则返回None
#如果能匹配上,通过group()获取匹配到的字符串
print(r0.group())
print(r1.group())


#. :可以匹配除了\n之外的所有的字符
r0 = re.match(r".","\n")
print(r0)

#[^xxx] :脱字符,表示否定
r0 = re.match(r"[^yang]","y")
print(r0)

#\d
r0 = re.match(r"\d","0")
print(r0)
r0 = re.match(r"[0-9]","0")
print(r0)

#\s,空白符[ \n\t\r\f]的匹配
r0 = re.match(r"\s","\n")
print(r0)

3.2多字符匹配
	"""
-------------------匹配多个字符------------------------

说明:下方的x、y、z均为假设的普通字符,n、m(非负整数),不是正则表达式的元字符
(xyz)    匹配小括号内的xyz(作为一个整体去匹配)
x?       匹配0个或者1个x
x*       匹配0个或者任意多个x(.* 表示匹配0个或者任意多个字符(换行符除外))
x+       匹配至少一个x
x{n}     匹配确定的n个x(n是一个非负整数)
x{n,}    匹配至少n个x
x{n,m}   匹配至少n个最多m个x。注意:n <= m
x|y      |表示或,匹配的是x或y
"""

"""
()   分组,一个()内部的数据表示一个整体
?    匹配0个或者1个
*    匹配0个或者多个
+    匹配1个或者多个
{}   匹配指定个数或者在指定区间内的个数的字符
|    正则1|正则2,只要正则1或者正则2中的任意一个匹配,则直接返回结果
"""
import  re

#findall:根据指定的规则查找指定的字符串,将字符串中符合条件的子字符串全部获取出来,返回一个列表
print(re.findall(r"a+","aaaaaaaaaaaaaaa"))
print(re.findall(r"a?","aaaaaaaaaaaaaaa"))
print(re.findall(r"a*","aaaaaaaaaaaaaaa"))
print(re.findall(r"a{3}","aaaaaaaaaaaaaaaa"))   #恰好
print(re.findall(r"a{3,}","aaaaaaaaaaaaaaa"))   #至少
print(re.findall(r"a{3,5}","aaaaaaaaaaaaaaaaaa"))  #区间
"""
['aaaaaaaaaaaaaaa']
['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', '']
['aaaaaaaaaaaaaaa', '']
['aaa', 'aaa', 'aaa', 'aaa', 'aaa']
['aaaaaaaaaaaaaaa']
['aaaaa', 'aaaaa', 'aaaaa', 'aaa']
"""

#search:根据指定的规则查找指定的字符串,从左往右依次查找,只要匹配到一个,则停止查找
#注意:search的底层调用的是match,如果匹配上,则返回一个对象,匹配不上返回None
print(re.search(r"a+","aaaaaaaaaaaaaaa"))
print(re.search(r"a?","aaaaaaaaaaaaaaa"))
print(re.search(r"a*","aaaaaaaaaaaaaaa"))
print(re.search(r"a{3}","aaaaaaaaaaaaaaaa"))
print(re.search(r"a{3,}","aaaaaaaaaaaaaaa"))
print(re.search(r"a{3,5}","aaaaaaaaaaaaaaaaaa"))
"""
<re.Match object; span=(0, 15), match='aaaaaaaaaaaaaaa'>
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 15), match='aaaaaaaaaaaaaaa'>
<re.Match object; span=(0, 3), match='aaa'>
<re.Match object; span=(0, 15), match='aaaaaaaaaaaaaaa'>
<re.Match object; span=(0, 5), match='aaaaa'>
"""

3.3贪婪匹配和非贪婪匹配
import  re

"""
贪婪匹配:尽可能多的匹配
非贪婪匹配:尽可能少的匹配
"""

#贪婪匹配
print(re.findall(r"\d+","2453645263436aaa-f5f5-3466bbv"))
print(re.findall(r"\d*","2453645263436aaa-f5f5-3466bbv"))

#非贪婪匹配
print(re.findall(r"\d?","2453645263436aaa-f5f5-3466bbv"))
"""
['2453645263436', '5', '5', '3466']
['2453645263436', '', '', '', '', '', '5', '', '5', '', '3466', '', '', '', '']
['2', '4', '5', '3', '6', '4', '5', '2', '6', '3', '4', '3', '6', '', '', '', '', '', '5', '', '5', '', '3', '4', '6', '6', '', '', '', '']
"""

#1.
print(re.findall(r"a\d+","a35475735673b"))
print(re.findall(r"a\d*","a35475735673b"))
"""
['a35475735673']
['a35475735673']
"""
print(re.findall(r"a\d+?","a35475735673b"))
print(re.findall(r"a\d*?","a35475735673b"))
"""
['a3']
['a']
"""

print("=" * 30)

#2
print(re.findall(r"\d+b","a35475735673b"))
print(re.findall(r"\d*b","a35475735673b"))
"""
['35475735673b']
['35475735673b']
"""
print(re.findall(r"\d+?b","a35475735673b"))
print(re.findall(r"\d*?b","a35475735673b"))
"""
['35475735673b']
['35475735673b']
"""

print("=" * 30)

#3
print(re.findall(r"a\d+b","a35475735673b"))
print(re.findall(r"a\d*b","a35475735673b"))
"""
['a35475735673b']
['a35475735673b']
"""
print(re.findall(r"a\d+?b","a354757356738989999b"))
print(re.findall(r"a\d*?b","a35475735673889999b"))
"""
['a35475735673b']
['a35475735673b']
"""

"""
结论:+或者*被称为贪婪匹配,?被称为非贪婪匹配
如果正则表达式的前面出现已知的限定条件,则在+或者*后面添加?则可以将贪婪匹配转换为非贪婪匹配
"""

3.4边界匹配
“”"
--------------锚字符(边界字符)-------------

^     行首匹配,和在[]里的^不是一个意思
$     行尾匹配

\A    匹配字符串开始,它和^的区别是,\A只匹配整个字符串的开头,即使在re.M模式下也不会匹配它行的行首
\Z    匹配字符串结束,它和$的区别是,\Z只匹配整个字符串的结束,即使在re.M模式下也不会匹配它行的行尾


\b    匹配一个单词的边界,也就是值单词和空格间的位置
\B    匹配非单词边界
"""
import  re

print(re.findall(r"^today","today is a good day"))   #startswith
print(re.findall(r"day$","today is a good day"))  #endswith

print(re.findall(r"^today","today is a good day\ntoday is a good day\ntoday is a good day"))
print(re.findall(r"day$","today is a good day\ntoday is a good day\ntoday is a good day"))
"""
['today']
['day']
"""

print(re.findall(r"^today","today is a good day\ntoday is a good day\ntoday is a good day",re.M))
print(re.findall(r"day$","today is a good day\ntoday is a good day\ntoday is a good day",re.M))
"""
['today', 'today', 'today']
['day', 'day', 'day']
"""

print(re.findall(r"\Atoday","today is a good day\ntoday is a good day\ntoday is a good day",re.M))
print(re.findall(r"day\Z","today is a good day\ntoday is a good day\ntoday is a good day",re.M))
"""
['today']
['day']
"""

#结论:re.M只对^和$起作用


#\b和\B
#\b匹配边界,\B匹配非边界
print(re.search(r"er\b","never"))
print(re.search(r"er\b","neraa"))

print(re.search(r"er\B","never"))
print(re.search(r"er\B","neraa"))
"""
<re.Match object; span=(3, 5), match='er'>
None
None
<re.Match object; span=(1, 3), match='er'>
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值