Python极简笔记(五)---异常、三神器

一、异常

1.1 常见标准异常

  • 异常名称
    异常名称注释
    AssertionError断言语句失败抛出
    AttributeError尝试访问未知的对象属性
    IndexError索引超出序列的范围
    KeyError字典中查找一个不存在的关键字
    KeyboardInterrupt用户输入中断键(Ctrl+c)
    MemoryError内存溢出(可通过删除对象释放内存)
    NameError尝试访问一个不存在的变量
    OSError操作系统产生的异常(例如打开一个不存在的文件)
    OverflowError数值运算超出最大限制
    SyntaxErrorPython的语法错误
    ZeroDivisionError除数为零

1.2 异常检测及处理

  • 标准模板
    # 监控语句块1,并捕获抛出的异常给except
    try:		
    	# 出错点以后的语句不会被执行				
    	语句块1			
    # 若出现异常名称1,程序会执行语句块2			
    except 异常名称1:				
    	语句块2
    # 多异常捕获(未列出的异常则正常抛出,且程序中断)
    except 异常名称2,异常名称3		
    	语句块3
    # 处理完try语句和except语句之后一定会执行的语句(即使有未捕获的异常)
    finally:			
    	语句块4
    
  • 异常引出
    # 主动引出异常:任何位置都可直接触发任何设定的异常
    raise ZeroDivisionError
    
    # 断言语句:断定表达式是True,否则,抛出asserterror异常
    num = 1
    assert 1 == num
    

二、迭代器

2.1 概念

  • 常规可迭代对象:列表、元组、字典、集合
  • 迭代器:操作迭代器可以依次读取可迭代对象的每一个值
    • 一次性:迭代到尾部,再操作迭代器会持续报错
    • 单向性:只可向队尾,不可指定方向及位置

2.2 构建及使用

  • 构建、判断迭代器
    # 操作列表
    In [1]: num = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    # num_iter类型:返回迭代器,
    In [2]: num_iter = iter(num)
    # 判断是否为迭代器方法:
    In [3]: from collections.abc import Iterator
    In [4]: isinstance(num_iter, Iterator)
    Out[4]: True
    
  • 使用迭代器
    # 方法一:若越界,见下面的越界异常
    In [5]: next(num_iter)
    Out[6]: 0
    
    # 方法二:若越界,见下面的越界异常
    In [7]: num_iter.__next__()
    Out[7]: 1
    
    # 方法三:遇到越界自动退出,不抛异常
    In [8]: for i in num_iter:
       ...:     print(i, end=" ")
    # 注意体会迭代器的单向性、一次性
    2 3 4 5 6 7 8 9    
    
    # 方法四:列表、元组化迭代获取
    # 1.列表化获取:首先重置迭代器
    In [9]: num_iter = iter(num)
    In [10]: list(num_iter)
    Out[10]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    # 2.元组化获取:首先重置迭代器
    In [11]: num_iter = iter(num)
    In [12]: tuple(num_iter)
    Out[12]: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    
  • 越界异常
    # 越界:抛出StopIteration异常
    In [13]: next(num_iter)
    --------------------------------------
    StopIteration    
    

三、生成器

  • 概述:其本质就是迭代器,对于庞大的可迭代对象,生成器只定义生成规则,不实际生成,每次调用生成器即只生成一个数据,节省内存,效率更高

  • 生成器表达式

    # 创建:涵盖0~10000000的数的平方生成规则
    # 	   注意与列表生成式区别,其为[]
    g = (x * x for x in range(10000000))
    type(g)
    >>> generator
    # 其也是迭代器
    isinstance(g, Iterator)
    >>> True
    # 生成器调用:同迭代器
    
  • 生成器函数

    def c_gen():
        num = 1
        while True:        
            # yield语句:含此语句则为生成器函数
            yield num
            num += 1
    f = c_gen()			
    # f为生成器				
    type(f)
    >>> generator
    # 生成器调用:同迭代器
    
  • 运行流程:

    • 调用生成器函数,内存加载生成器函数,生成器运行到yield语句,暂停,
      生成器函数若未越界则驻留内存
    • 将值(num)弹给调用处,跳出生成器,并记录跳出点
    • 下次生成器再次被调用,则从上次跳出的yield下一条语句继续执行

四、装饰器(函数式编程)

  • 功能:在不改变原有函数的基础上增加新功能的机制,装饰器可以加在多个函数身上,来为函数增加装饰器所具有的功能,而调用的函数名还是原函数名

4.1 闭包(装饰器理解的基础)

4.1.1 定义

  • 闭包函数:声明在一个函数中的函数,叫做闭包函数
  • 闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
  • 特点:可以避免使用全局变量,防止全局变量污染;让外部访问函数内部变量成为可能;会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

4.1.3 实例

  • 代码示例
    # outer是外部函数 a和b都是外函数的临时变量,功能实现结束后
    # 会自动在内存中销毁outer所指向的内存,见下解释
    def outer( a ):						
    	b = 10
    	# inner是内函数,闭包函数,因创建outer时才会创建inner
    	# 所以每次创建都彼此独立,见下解释
    	def inner():				
    		# 在内函数中,用到了外函数的临时变量
    		print(a+b)					
    	# 外函数的返回值是内函数的引用			
    	return inner					
    		
    if __name__ == '__main__':
    	# 返回了函数名inner,且a和b的值都已确定,
    	# 只是做了个引用,不会有任何显示
    	demo1 = outer(5)
    	# 相当于inner(),且其内的a,b值都已确定
    	demo1() 								
    			
    	# 此处即使改变outer()的函数体,demo()的值也不会改变,
    	# 但会影响demo2				
    	demo2 = outer(7)			
    	# 打印输出17		
    	demo2()								
    
  • demo1定义:demo1 = outer(5)
    1. 我们调用outer函数,outer函数创建了inner函数,然后把inner函数的引用返回并存给了demo
    2. 外部函数outer()结束任务,启动销毁
    3. 外函数销毁的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数,内部函数inner因为被外部的demo引用,也不能销毁,所以只有def行return行销毁,其他常驻内存
  • demo1使用:demo1()
    1. demo()的函数名demo此时包含了两个内在属性,def inner() 和变量b = 10, a
    2. 变量b只读:因为变量b是inner()函数的外部变量,又因为外部函数可以读取并修改内部函数的变量,内部函数只可向上逐层读取外部函数的变量,但不可修改外部函数的变量
    3. 不可变性:因为demo = outer(5)语句后,inner函数和外部变量b就常驻内存了,整个程序不结束,二者的函数体和变量值就不可变,即不可变性
  • demo2定义:demo2 = outer(7)
    1. demo1 = outer(5)同样绑定流程及销毁流程
    2. 常驻内存部分:其常驻内存部分与demo1 = outer(5)的常驻内存部分各自独立,完全不相关,无限制创建会导致内存泄露

4.2 装饰器构建

  • 多个装饰器:其应用顺序是按照自底向上
  • 核心点:装饰器核心点是针对函数名的运算
  • 无输入值的装饰器
    # 装饰器定义:定义无输入值(除了函数名func)的闭包,
    #			func为外部嵌套函数中的变量
    def c_dec(func):	
    	# 闭包要素一:内部函数wrapper_in(*argv,**kw)				
    	def wrapper_in(*argv,**kw):		
    	    # 顺序执行语句一: 此处为新增的功能,每次重写这里即可
    	    # 			   其他位置都是不变的
    		print('这是内函数语句')
    		# 顺序执行语句二:执行原函数
    		# 闭包要素二:调用了外部函数的变量
    		func(*argv,**kw)	
        # 闭包要素三:返回内嵌函数名	
        return wrapper_in			
        		
    #########################################################
    # 装饰器使用:功能相当于语句 now = c_dec(now) 
    @c_dec						
    def now(*argv,**kw):	
    	# 函数功能就是:传进来什么就打印什么			
        print(*argv,**kw)	
        
    #########################################################    			
    # 调用now函数:此时 now('good')
    #			等价于 c_dec(now)('good')
    #			等价于 wrapper_in('good')
    now('good')							
    
    #########################################################    
    >>>这是内函数语句
    >>>good
    
  • 有输入值的装饰器
    # 首层传装饰器的输入值:多层嵌套实现传参
    def c_dec(text):					
        def decorator(func):				
    # --------跟无输入值装饰器一样:起始--------
            def wrapper_in(*args, **kw):	
      		    # 顺序执行语句一: 此处为新增的功能,每次重写这里即可
       			# 其他位置都是不变的		
                print("接收到的字符串是:" + text)
                # 这是执行被修饰的原函数
                func(*args, **kw)	
            return wrapper_in					
    # --------跟无输入值装饰器一样:结束---------    
        return decorator	
    
    #########################################################	
    # 传入参数的装饰器:字符串传给c_dec函数
    @c_dec('execute')						
    def now(*args,**kw):					
        print(*args,**kw)
        
    #########################################################    			
    # 调用now函数:此时 now('good')
    # 			等价于 c_dec('execute')(now)('good')
    #			等价于 decorator(now)('good')
    #			等价于 wrapper_in('good')
    now('good')								
    
    #########################################################
    # 新增的功能
    >>>接收到的字符串是:execute
    # 函数的原功能
    >>>good 
    
  • 装饰器充要条件
    • 必须有一个内嵌函数
    • 内嵌函数必须引用外部嵌套函数中的变量
    • 外部函数返回值必须是内嵌函数名
  • 类实现装饰器:详见下一篇

回到总目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值