day27:异常&反射

目录

认识异常处理

  1.程序错误的种类

    2.异常的分类

  3.AssertionError(断言assert语句失败)

异常处理的基本语法

  1.异常处理的基本语法

  2.带有分支的异常处理

  3.处理迭代器异常错误

异常处理的其他写法

  1.try ... finally ...

  2.try ... except ... else ...

  3.try ... except ... else ... finally ...

raise:主动抛出异常

  1.关于raise你需要知道

  2.raise的基本语法

自定义异常类

反射

  1.反射类当中的成员

  2.反射模块当中的成员

  3.反射综合案例

认识异常处理

1.程序错误的种类

程序错误分为两种:语法错误异常错误

1.语法错误:代码没有按照python规定语法去写,发明创造产生的错误

2.异常错误:在代码语法正确的前提下,程序报错就是异常

2.异常的分类

# IndexError                索引超出序列的范围
# KeyError                  字典中查找一个不存在的关键字
# NameError                 尝试访问一个不存在的变量
# IndentationError          缩进错误
# AttributeError            尝试访问未知的对象属性
# StopIteration             迭代器没有更多的值
# AssertionError             断言语句(assert)失败
# EOFError                  用户输入文件末尾标志EOF(Ctrl+d)
# FloatingPointError        浮点计算错误
# GeneratorExit             generator.close()方法被调用的时候
# ImportError               导入模块失败的时候
# KeyboardInterrupt         用户输入中断键(Ctrl+c)
# MemoryError               内存溢出(可通过删除对象释放内存)
# NotImplementedError       尚未实现的方法
# OSError                   操作系统产生的异常(例如打开一个不存在的文件)
# OverflowError             数值运算超出最大限制
# ReferenceError            弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
# RuntimeError              一般的运行时错误
# SyntaxError               Python的语法错误
# TabError                  Tab和空格混合使用
# SystemError               Python编译器系统错误
# SystemExit                Python编译器进程被关闭
# TypeError                 不同类型间的无效操作
# UnboundLocalError         访问一个未初始化的本地变量(NameError的子类)
# UnicodeError              Unicode相关的错误(ValueError的子类)
# UnicodeEncodeError        Unicode编码时的错误(UnicodeError的子类)
# UnicodeDecodeError        Unicode解码时的错误(UnicodeError的子类)
# UnicodeTranslateError     Unicode转换时的错误(UnicodeError的子类)
# ValueError                传入无效的参数
# ZeroDivisionError         除数为零

3.AssertionError(断言assert语句失败)

什么是断言?

断言就是的意思

assert 和 if 之间的区别在于

assert 在断言失败时候,是直接报错,抛出异常,后面的代码直接终止

if 在判断为False 的时候,不执行代码

assert 3>1
assert 3>1000
print("ok")

 异常处理的基本语法

1.异常处理的基本语法

try ... except ...

有问题的代码放到try这个代码块当中

如果出现了异常,会直接执行except这个代码块中的内容

作用:防止异常抛错,终止程序.

try :
    lst = [1,2,3]
    print(lst[90])
except:
    print("这里有异常错误~")

2.带有分支的异常处理

在说这个之前,先说一个语法:

except + 异常错误类:特指发生在这类异常错误时,要执行的分支

try:
    # IndexError
    # lst = [1,2,3]
    # print(lst[90])
    
    # KeyError
    # dic = {}
    # print(dic["a"])
    
    # NameError
    # print(wangwen)
    
except IndexError:
    print("索引超出了范围")
    
except KeyError:
    print("字典中没有这个键")

except NameError:
    print("没有这个变量")

except:
    print("有异常错误...")

:)看这个结构,有些像 if elif elif else的感觉

3.处理迭代器异常错误

def mygen():
    print("start ... ")
    yield 1
    yield 2
    yield 3
    return 4

gen = mygen()
try:
    res = next(gen)
    print(res)
    res = next(gen)
    print(res)
    res = next(gen)
    print(res)
    res = next(gen)
    print(res)
    
except StopIteration as e :
    # 为当前异常错误类StopIteration的对象起一个别名叫做e
    # 在StopIteration内部有__str__的方法
    # 在打印对象时,直接获取生成器中的return的返回值.
    print(e)
    print("生成器停止迭代")

看到了这段代码,有几个问题需要注意:

1.except StopIteration as e:StopIteration是一个异常错误类,e是错误类对象的别名

2.在StopIteration异常类中,内置了__str__方法,在打印e对象时,可以直接获取到生成器中的return返回值

异常处理的其他写法

1.try ... finally ...

不论代码正确与否,都必须执行的代码放到finally当中.

一报错会终止掉程序,后面的代码不执行

有些必须要走的代码写在finally中

 

try:
    lst = [1,2,3]
    print(lst[90])
finally:
    print("被触发了..")

print(123)

2.try ... except ... else ...

如果try这个代码块没有异常错误,执行else这个分支,反之就不执行

try:
    lst = [1,2,3]
    print(lst[90])
except:
    pass
else:
    print("正常执行结束...")

3.try ... except ... else ... finally ...

try内代码块的代码如果有异常,执行except代码块

                         如果没有异常,执行else代码块

        不管有没有异常,最后都要走finally代码块

try:
    lst = [1,2,3]
    print(lst[90])
except:
    print("异常处理222")
else:
    print("正常执行结束...")
finally:
    print("我被执行了111")

raise:主动抛出异常

关于raise你需要知道

基本格式:raise + 异常错误 or 异常错误类对象

常见的两个父类:

  BaseException 所有异常类的父类(基类,超类)

  Exception 常见异常类的父类

raise的基本语法

# 基本语法
try:
    raise BaseException # 相当于主动制造出一个错误
except BaseException:
    pass
    
# 简写
try:
    raise
except:
    print("有异常错误")

自定义异常类

定义一个自定义异常类MyException,让此类继承BaseException类

#(了解)系统底层获取行数和文件名的函数( 只有在程序异常时才能触发 ) 
def return_errorinfo(n):
    import sys
    f = sys.exc_info()[2].tb_frame.f_back
    if n==1:        
        return str(f.f_lineno)      #返回当前行数
    elif n == 2:    
        return f.f_code.co_filename #返回文件名    


def get_value(n):
    try:
        raise
    except:
        return return_errorinfo(n)


class MyException(BaseException):
    def __init__(self,num,msg,line,file):
        # 错误号
        self.num = num
        # 错误信息
        self.msg = msg
        # 错误行号
        self.line = line
        # 错误文件
        self.file = file


sex = "雌雄同体"
try:
    if sex == "雌雄同体":
        # raise + 异常错误类 或者 异常错误类对象
        raise MyException(404,"醒醒吧老弟,人类没有雌雄同体~",get_value(1),get_value(2))

except MyException as e:
    # 对象.属性 
    print(e.num)
    print(e.msg)
    print(e.line)
    print(e.file)
    
    

反射

概念: 通过字符串去操作类对象或者模块当中的成员(属性或者方法)

class Man():
    pass

class Woman():
    pass

class Children(Man,Woman):
    skin = "绿色"
    
    def eat(self):
        print("小孩一下生就拿了两串大腰子出来了")

    def drink(self):
        print("小孩一下生拿了两瓶勇闯天涯出来了")
    
    def __suger(self):
        print("小孩自个的糖糖是不给别人的...")
        
obj = Children()

1.反射类当中的成员

1.hasattr() 检测对象/类是否有指定的成员

# hasattr() 检测对象/类是否有指定的成员
# 对象
res = hasattr(obj,"skin") # 检测obj对象是否有成员skin
print(res)

#
res = hasattr(Children,"eat") # 也可以检测类中是否有成员eat
res = hasattr(Children,"__suger") # 私有成员不能访问,所以结果为False
print(res)

2.getattr() 获取对象/类成员的

# getattr() 获取对象/类成员的值
# 对象
res = getattr(obj,"skin") # 对象反射属性
print(res)

# 通过对象反射出来的方法是个绑定方法,不需要在func添加参数,obj会自动传进去
func = getattr(obj,"drink")
func()

#
# 通过类反射出来的方法是个普通方法,需要添加参数,避免形参实参数量不一致
func = getattr(Children,"eat")
func(1)

# 反射的成员不存在时,可以设置一个默认值防止报错
res = getattr(obj,"abcdefg1234","该成员不存在")
print(res)

3.setattr() 设置对象/类成员的值

# 对象
setattr(obj,"eye","白色")
print(obj.eye)

#
setattr(Children,"sex","女性")
print(Children.sex)
print(obj.sex)

4.delattr() 删除对象/类成员的值 

delattr(obj,"eye")
print(obj.eye)  # error

#
delattr(Children,"sex")
Children.sex

2.反射模块当中的成员

import sys
print(sys.modules) # 返回的是系统模块的一个字典

# 获取当前本模块的对象 (通过__main__这个键来获取)
print(sys.modules["__main__"])
# <module '__main__' from '/mnt/hgfs/python31_gx/day27/mymodule4.py'>



def func1():
    print("我是func1方法")

def func2():
    print("我是func2方法")

def func3():
    print("我是func3方法")

def func4():
    print("我是func4方法")

3.反射综合案例

while True:
    selfmodule = sys.modules["__main__"] # 获取当前模块对象
    strvar = input("请输入你要反射的方法")
    if hasattr(selfmodule,strvar): # 判断当前模块是否有你输入的方法
        func = getattr(selfmodule,strvar) # 获取到你输入的方法名
        func()
    else:
        print("没有这个方法")

 

posted @ 2020-08-10 21:38  iR-Poke  阅读(217)  评论(0编辑  收藏  举报