骄傲的赛亚人

装饰器

闭包

函数内部作用域定义的变量和函数,只能在函数内部使用(外部无法直接访问和修改)

函数外部要使用局部作用域内的数据,只能通过return返回出去

闭包函数 = 函数 + 保存引用数据的封闭作用域`

闭包的特征:

  1. 函数中嵌套一个函数
  2. 外层函数rertun返回 内层函数
  3. 内层函数有引用 **外部作用域** 的非全局变量

 简单的闭包:

 

 

 

 

装饰器:


定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能

作用:在不更改原功能函数内部代码,并且不改变调用方法的情况下为源代码添加新功能
原则:
1、不能修改被装饰函数的源代码
2、不能修改被装饰的函数的调用方式

实现装饰器知识储备
1、函数既变量
2、高阶函数
把函数名当作一个实参传递给另一个函数
返回值中包含函数名
3、嵌套函数
高阶函数+嵌套函数=装饰器
"""

 

基础装饰器:

 

 

 

 

 func_demo(2,3)

输出:

-----装饰器的扩展功能--1----

a除B的结果为: 0.6666666666666666

 

装饰器的副作用:

print(func_demo.__name__)  打印函数的名称

print(func_demo.__doc__)    打印函数的注释说明

在函数func_demo使用装饰器func后,打印func_demo的函数名,和函数说明,会打印出wrapper的函数名和函数说明

为了消除这一副作用,需要引入模块 :from functools import wraps 

 

 

 装饰器装饰类

 

 

 注意:

  在装饰类的时候在调用原来类的对象的时候,一定要用一个变量接受,然后对变量进行返回,不加return类就不能创建对象

 

普通的通用装饰器

 1 import time
 2 
 3 
 4 def fun1(ff):
 5     def count_time(*args, **kwargs):
 6         start_time = time.time()
 7         res = ff(*args, **kwargs)
 8         end_time = time.time()
 9         print('函数执行的时间:', end_time-start_time)
10         return res
11     return count_time
12 
13 @fun1 # work1=count_time(work1)
14 def work1():
15     time.sleep(0.5)
16     print("这是work1")
17 
18 @fun1 # work2=count_time(work2)
19 def work2(a,b):
20     time.sleep(0.8)
21     print("work2函数的功能",a+b)
22 
23 work1()
24 work2(1,2)

 

 

可以传参数的装饰器

def decorator(name):
    """最外层的参数是装饰器的参数"""
    def wrapper1(func):
        """第二次定义的参数,接收被装饰的函数"""
        def wrapper2(*args, **kwargs):
            print("-----装饰器的扩展功能代码111")
            print("装饰器传入的参数name:", name)
            # 执行被装饰的函数
            res = func(*args, **kwargs)
            print("-----装饰器的扩展功能代码222")
            return res
        return wrapper2
    return wrapper1


@decorator('tom')  # work = decorator('tom')(work)   decorator('tom')等于wrapper1
def work():
    print('--------------work------------------')

缓存装饰器lru_cache:

256的单位是bytes

对同一个函数相同的入参执行的结果进行缓存,通常用于提升递归函数的效率

例:用一个函数得,传一个int正整数,得到斐波那契数列的第几位数

 

 输出:34

 

通过类实现装饰器

class Decorator():
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("装饰器扩展的代码")
        # 调用原功能函数
        self.func(*args, **kwargs)


@Decorator
def work(a,b):  # work = Decorator(work)
    print("--------work--------")
    print(a+b)


work(10,30)

 

练习题

1、设计一个装饰器,接受一个int类型的参数number,可以用来装饰任何函数,如果函数运行的时间大于number,则打印出函数名和函数的运行时间

 1 def fun1(num):
 2     def fun2(ff):
 3         def fun3(*args,**kwargs):
 4             s_time = time.time()
 5             ff(*args,**kwargs)
 6             e_time = time.time()
 7             run_time = e_time-s_time
 8             if run_time > num:
 9                 print('函数运行时间:{}'.format(run_time))
10                 print('函数名{}'.format(ff.__name__))
11         return fun3
12     return fun2
13 
14 @fun1(1)
15 def work():
16     time.sleep(2)
17     print("这是work功能")
18 
19 work()

2、实现一个重运行的装饰器,可以用来装饰任何一个功能函数,只要被装饰的函数出现AssertionError,则重新执行该函数,同一个函数最多运行三次

 1 def fun1(ff):
 2     def fun2(*args,**kwargs):
 3         for i in range(1,4):
 4             try:
 5                res = ff(*args,**kwargs)
 6             except AssertionError as e:
 7                 if i==3:
 8                     raise e
 9             else:
10                 print("执行通过")
11                 return res
12                 # break
13     return fun2
14 
15 @fun1
16 def work2():
17     expected = 'abc'
18     res = input("请输入:")
19     assert expected == res
20 
21 
22 work2()

 

posted on 2022-02-22 11:47  骄傲的赛亚人  阅读(46)  评论(0编辑  收藏  举报

导航