• 闭包函数,函数装饰器,语法糖


    一.闭包函数:

    闭包函数:
    闭:定义在函数内部的函数
    包:内部的函数引用了外部函数作用域的名(变量名)
    闭包也是一种传参方式

    def outter(x,y):
        # x = 1
        # y = 2
        def my_max():
            if x > y:
                return x
            return y
        return my_max
    res = outter(1,2)   # outter加()本身会得到一个返回值my_max,实参1和2相当于变量值传给了x和y两个变量名
    print(res())
    
    

    import requests  # 爬虫模块
    
    #方式一 直接给函数传参
    info1 =  'https://www.baidu.com'
    info2 = '......'
    def my_get(rul):
        resuit = requests.get(rul)
        if resuit.status_code == 200:
            print(len(resuit.text))
    my_get(info1)
    my_get(info2)
    '.....'
    
    
    #方式二 用闭包的方式给函数传参
    def outter(func):
        # func =  'https://www.jd.com'
        def my_get(func):
            resuit = requests.get(func)
            if resuit.status_code == 200:
                print(len(resuit.text))
        return my_get
    res_jd = outter( 'https://www.jd.com')  # res = my_get
    res_jd()  # my_get()

    二.装饰器:

    装饰器
    器:就是一个工具
    装饰:给被装饰对象(函数)添加功能
    开放封闭原则:
    开放:对扩展开放
    封闭:对修改封闭

    装饰器(被调用对象)必须遵循的两大原则:
    1.不改变装饰对象(被装饰函数)的源码
    2.不改变被装饰对象的调用方式
     import time
    print(time.time())
    # 1562812014.731474 时间戳  当前时间距离1970-1-1 00:00:00相差的秒数
    # 1970-1-1 00:00:00是Unix诞生元年
    
    
     time.sleep(3)  # 让cpu谁三秒   让你的程序暂停三秒
     print('FBI!')
    time 模块

     通用装饰器模板

    def outter(func):
        def inner(*args,**kwargs):
            print('执行被装饰函数之前 你可以做的操作')
            res = func(*args,**kwargs)
            print('执行被装饰函数之后 你可以做的操作')
            return res
        return inner
    def auth(driver='file'):
        def auth2(func):
            def wrapper(*args,**kwargs):
                name=input("user: ")
                pwd=input("pwd: ")
    
                if driver == 'file':
                    if name == 'egon' and pwd == '123':
                        print('login successful')
                        res=func(*args,**kwargs)
                        return res
                elif driver == 'ldap':
                    print('ldap')
            return wrapper
        return auth2
    
    @auth(driver='file')
    def foo(name):
        print(name)
    
    foo('egon')
    
    有参装饰器
    统计func函数运行时间:
    # 简单版:
    def func():
        time.sleep(2)  # 让cpu睡眠2秒
        print('form func')
    
    star_res = time.time()
    func()
    over_res = time.time()
    print('运行时间: %s'%(over_res - star_res))
    # >>> 运行时间: 2.00064754486084
    #此时的计算时间功能只能func函数单独使用,如果其他函数也要用到时间计算功能需要重新编写代码,
    # 可以把计算时间功能封装成一个函数给其他函数使用
    
    
    #有装饰器版
    
    def func():
        time.sleep(2)  # 让cpu睡眠2秒
        print('form func')
    
    def outter(info):  # info = 原始func的内存地址
        def time_func():
            star_res = time.time()
            info()  # 相当于 func() 函数运行
            over_res = time.time()
            print('运行时间: %s'%(over_res - star_res))
        return time_func
    func = outter(func)  # 新 func = time_func的内存地址
    func()  # 相当于 time_func()函数运行
    
    # >>> form func
    # >>> 运行时间: 2.0006558895111084
    import time
    def index():
        time.sleep(3)
        print('澳门最大线上赌场开业啦 性感tank在线发牌!')
        return 'index'
    # res1 = index()
    
    def login(name):
        time.sleep(1)
        print('%s is sb'%name)
        return 'login'
    # res = login('egon')
    
    def outter(func):  # func = 最原始的login函数的内存地址
        def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
            start = time.time()
            res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    login = outter(login)  # outter(最原始的login函数的内存地址)
    res = login('egon')
    print(res)
    # >>>egon is sb
    # >>>func run time:1.000328779220581
    # >>>login
    
    index = outter(index)
    res1 = index()
    print(res1)
    # >>>澳门最大线上赌场开业啦 性感tank在线发牌!
    # >>>func run time:3.0011234283447266
    # >>>index
    利用*args和**args解决有参无参均可调用问题

    在装饰器内,定义形参 *args ,**kwargs 可以接收有参无参函数

    def func():
        time.sleep(2)  # 让cpu睡眠2秒
        print('form func')
        return '函数func的返回值'
    
    def user(name):
        time.sleep(1)
        print('welcome %s'%name)
        return '函数user的返回值'
    
    def outter(info):  # info = 原始func的内存地址  # info = 原始user的内存地址
        def time_get(*args,**kwargs):
            # args = ' '
            # kwargs = ' '  闭包函数的特性
            star_res = time.time()
            res = info(*args,**kwargs)  # 相当于 func() 函数运行  # 相当于user()函数运行,但函数user必须要传参才能执行
            over_res = time.time()
            print('运行时间: %s'%(over_res - star_res))
            return res
        return time_get
    func = outter(func)  # 新 func = time_get的内存地址
    res_1 =func()  # 相当于 time_get()函数运行
    print(res_1)   # res_1 = res = 函数func的返回值
    # >>> form func
    # >>> 运行时间: 2.0006558895111084
    # >>> 函数func的返回值
    
    user = outter(user)  # 新 user = rime_get 的内存地址
    res_2 = user('wong')  # 相当于 time_get()运行函数
    print(res_2)
    # >>> welcome wong
    # >>> 运行时间: 1.000464677810669
    # >>> 函数user的返回值

     

    三.语法糖 @+装饰器函数名

    语法糖在书写的时候应该与被装饰对象紧紧挨着 
    两者之间不要有空格

    @+装饰器函数名        相当于它拿到了它所装饰的哪个函数的内存地址,当作实参传给装饰器的形参

    import time
    
    def outter(info):  # info = 原始func的内存地址  # info = 原始user的内存地址
        def time_get(*args,**kwargs):
            # args = ' '
            # kwargs = ' '  闭包函数的特性
            star_res = time.time()
            res = info(*args,**kwargs)  # 相当于 func() 函数运行  # 相当于user()函数运行,但函数user必须要传参才能执行
            over_res = time.time()
            print('运行时间: %s'%(over_res - star_res))
            return res
        return time_get
    # func = outter(func)  # 新 func = time_get的内存地址
    # res_1 =func()  # 相当于 time_get()函数运行
    # print(res_1)
    
    @outter  # func = outter(func)
    def func():
        time.sleep(2)  # 让cpu睡眠2秒
        print('form func')
        return '函数func的返回值'
    func()
    
    @outter  # user = outter(func)
    def user(name):
        time.sleep(1)
        print('welcome %s'%name)
        return '函数user的返回值'
    user('wong')
    
    
    # 装饰器在装饰的时候  顺序从下往上
    # 装饰器在执行的时候 顺序从上往下
    def outter1(func1): #func1=wrapper2的内存地址
        print('加载了outter1')
        def wrapper1(*args,**kwargs):
            print('执行了wrapper1')
            res1=func1(*args,**kwargs)  # func1=wrapper2的内存地址
            return res1  
        return wrapper1
    
    def outter2(func2): #func2=wrapper3的内存地址
        print('加载了outter2')
        def wrapper2(*args,**kwargs):
            print('执行了wrapper2')
            res2=func2(*args,**kwargs)  # func2=wrapper3的内存地址  相当于wrapper3() 并执行 
            return res2
        return wrapper2
    
    def outter3(func3): # func3=最原始的那个index的内存地址
        print('加载了outter3')
        def wrapper3(*args,**kwargs):
            print('执行了wrapper3')
            res3=func3(*args,**kwargs)  # func3=最原始的那个index的内存地址  相当于 index() 并执行 
            return res3
        return wrapper3
    
    @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
    @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
    @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址  # wrapper = outter3(index)
    def index():  # func3(*args,**kwargs)的时候运行此函数
        print('from index')  # 最后一步
    index()  # 相当于 wrapper1()
    多层装饰器
    
    

     详情分析链接



  • 相关阅读:
    js中实现继承的几种方式
    js中prototype,__proto__,constructor之间的关系
    圣杯布局
    BFC详解
    Altium制作DC002的PCB封装和3D模型
    直流供电电路中,关于电源并联二极管、电容作用的思考与总结
    AltiumDesigner17快捷键
    AltiumDesigner17学习指南
    AltiumDesigner元器件搜索中英文对照
    智慧树自动刷课脚本
  • 原文地址:https://www.cnblogs.com/waller/p/11171478.html
Copyright © 2020-2023  润新知