• Python-Basis-9th


    周四,晴,记录生活分享点滴

    参考博客:https://www.cnblogs.com/yuanchenqi/articles/5830025.html

    推荐阅读:https://www.runoob.com/w3cnote/python-func-decorators.html

    Python版本:3.5

    装饰器前期

    作用域

    https://www.cnblogs.com/chungzhao/p/12973075.html  5.0

    函数即对象

    函数对象的调用比其它对象多了一个(),foo,bar与a,b一样都是个变量名

    只有函数加载到内存才可以被调用

    1. 可以被赋给其他变量 

    def foo():
        print('foo')
    bar=foo
    bar()
    foo()
    print(id(foo),id(bar))  #4321123592 4321123592

    2. 可以被定义在另外一个函数内(作为参数&作为返回值)

    # *******函数名作为参数**********
    def foo(func):
        print('foo')
        func()
    
    def bar():
        print('bar')
    
    foo(bar)
    # foo  bar
    
    
    # *******函数名作为返回值*********
    def foo():
        print('foo')
        return bar
    
    def bar():
        print('bar')
    
    b = foo()
    b()
    # foo  bar

    函数的嵌套以及闭包

    嵌套函数 

    name = "Chung"
    
    def change_name():
        name = "Chung2"
    
        def change_name2():
            name = "Chung3"
            print("第3层打印", name)  ## 第3层打印 Chung3
    
        change_name2()  # 调用内层函数
        print("第2层打印", name)  ## 第2层打印 Chung2
    
    change_name()
    print("最外层打印", name)  ## 最外层打印 Chung
    
    # 各个 print 与 函数 位于同一级别

    闭包函数

    https://blog.csdn.net/weixin_44141532/article/details/87116038

    闭包格式:

    def 外层函数(参数):
        def 内层函数():
            print("内层函数执行", 参数)
    
        return 内层函数
    
    
    内层函数的引用 = 外层函数("传入参数")
    内层函数的引用()

    闭包举例:

    def func(a, b):  #1.外函数func有接收参数 a=2,b=3
        def line(x):  #2.内函数line接收参数x=5
            return a * x - b  #3.在内函数体中计算了a*x-b 即 2×5-3的值作为返回值
    
        return line  #4.外函数返回内函数的引用(这里的引用指的是内函数line在内存中的起始地址,即第二、三行)  #5.最终调用内函数line()得到返回值7
    
    line = func(2, 3)
    print(line(5))
    
    # 7

     小结:闭包的核心是在返回时的引用,引用的是自己里面的那一层,这一层在内存中。

     

    装饰器概念

    作用

    装饰器可以让其他函数在不需要修改代码的前提下增加额外的功能,抽离出大量与函数功能本身无关的雷同代码并继续重用。

    简要概括是为已经存在的对象添加额外的功能

    返回值

    装饰器的返回值也是一个函数对象

    应用场景

    经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景

     

    简单装饰器

    常规

    通过 show_time(foo) 返回一个函数对象,这个函数对象内是核心业务(干活儿的)函数:执行func()与装饰函数时间计算

    import time
    # ------------------------------------- #
    def show_time(func):
        def wrapper():
            start_time=time.time()
            func()
            end_time=time.time()
            print('spend %s'%(end_time-start_time))
     
        return wrapper
    
    # ------上面是装饰器函数,下面是功能函数----- #
    
    def foo():
        print('hello foo')
        time.sleep(3)
    # -------------------------------------- #
    foo=show_time(foo)
    foo()

    @ 语法糖

    避免再一次赋值操作

    省去foo=show_time(foo)或者bar = show_time(bar)这句,直接调用foo()或者bar()得到结果

    import time
     
    def show_time(func):
        def wrapper():
            start_time=time.time()
            func()
            end_time=time.time()
            print('spend %s'%(end_time-start_time))
     
        return wrapper  # wrapper为闭包函数
     
    @show_time   #foo=show_time(foo)
    def foo():
        print('hello foo')
        time.sleep(3)
     
     
    @show_time  #bar=show_time(bar)
    def bar():
        print('in the bar')
        time.sleep(2)
     
    foo()
    print('***********')
    bar()

    @show_time的作用是指在执行业务逻辑foo()时,执行的代码由粉框部分转到蓝框部分

    被装饰函数的参数

    给功能函数加参数

    #***********不定长参数**************
    import time
    
    def show_time(func):
    
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print('spend %s'%(end_time-start_time))
    
        return wrapper
    
    @show_time   #add=show_time(add)
    def add(*args,**kwargs):  # 给功能函数加参数
    
        time.sleep(1)
        sum=0
        for i in args:
            sum+=i
        print(sum)
    
    add(2,4,8,9)

    带参数的装饰器

    在上面的装饰器调用中,比如@show_time,该装饰器唯一的参数就是执行业务的函数

    装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a),可以继续添加参数来实现更多的功能

    import time
    def logger(flag=''):  # 多增加了一个函数 = 多增加了一个功能:打印'文件目录'
        def show_time(f):
            def inner(*x, **y):
                start = time.time()
                f(*x, **y)
                end = time.time()
                print('spend %s' % (end - start))
    
                if flag == 'true':
                    print('日志记录')  #新增的功能
    
            return inner
    
        return show_time
    
    @logger('true')  # 与if flag == 'true'相对应
    def add(*a, **b):
        time.sleep(1)
        sums=0
        for i in a:
            sums += i
        print(sums)
    
    add(1, 2, 5)  #8  spend 1.0103797912597656  日志记录
    
    
    @logger('')  # 如果没有输入true,不会打印日志记录
    def bar():
        time.sleep(2)
        print('hello')
    bar()  # hello  spend 2.008728265762329
  • 相关阅读:
    特征工程系列:GBDT特征构造以及聚类特征构造
    SQL语句优化,数据分析师必须掌握!
    Win8下修改任務欄的資源管理器默認打開位置
    eclipse升级,导入旧版eclipse的插件[转]
    内网Linux对公网开启SSH
    windows上传文件到linux
    Chrome每次打開都要打開123.sogou.com
    maven下载的jar文件出现invalid LOC header (bad signature)
    requesting java ast from selection
    JConsole connection failed
  • 原文地址:https://www.cnblogs.com/chungzhao/p/12982607.html
Copyright © 2020-2023  润新知