zoukankan      html  css  js  c++  java
  • 闭包函数、无参装饰器

    闭包函数:函数内部定义函数,成为内部函数。该内部函数包含对外部作用域,而不是对全局作用域名字的引用,那么该内部函数成为闭包函数。

    复制代码
    name='alex'     #定义全局变量name='alex'
    def func():
        name='egon'  #定义局部变量name='egon'
        def bar():
            print(name)
        return bar    #返回bar函数名
    
    b=func()    #执行func()结果为bar的函数名  相当于b=bar
    name='haha'  #重新定义全局变量name='haha'
    print(b)    #打印bar
    b()       #执行bar(),name='egon'
    
    执行结果: <function func.<locals>.bar at 0x000000000222BAE8> egon
    复制代码
    复制代码
    def func():
        name='egon'
        x=1000000000000000000000
        def bar():
            print(name)
            print(x)
        return bar
    f=func()
    print(f.__closure__)    #打印出闭包函数外层作用域的变量
    print(f.__closure__[0].cell_contents)  #打印出闭包函数外层作用域的第一个变量的值
    print(f.__closure__[1].cell_contents)  #打印出闭包函数外层作用域的第一个变量的值
    运行结果:
    (<cell at 0x0000000001E16528: str object at 0x0000000001E993B0>, <cell at 0x0000000001E16558: int object at 0x0000000001EA3C10>)
    egon
    1000000000000000000000
    复制代码

    闭包函数:1 内部函数 2 包含对外部作用域而非全局作用域的引用
    闭包函数的特点:
        自带作用域
        延迟计算

    以上两个实例都是包一层,闭包函数可以包多层:

    复制代码
    #包两层的闭包函数
    def func():
        name='egon'     #第2层作用域的变量
        def wrapper():
            money=1000      #第1层作用域的变量
            def tell_info():
                print('my namn is %s' % name)   #使用第2层作用域的变量
                print('egon have money %s' %(money))    #使用第1层作用域的变量
            print(tell_info.__closure__)        #打印闭包函数的变量
            return tell_info
        return wrapper
    w=func()
    tell_info=w()
    print(tell_info.__closure__[0].cell_contents)  #闭包函数变量位置在定义时就定下来了,不因为使用的顺序变化
    print(tell_info.__closure__[1].cell_contents)
    运行结果:
    (<cell at 0x0000000001E16558: int object at 0x000000000048AED0>, <cell at 0x0000000001E16528: str object at 0x0000000001E993B0>)
    1000
    egon
    复制代码

    定义闭包函数的基本形式:

    复制代码
    def 外部函数名():
        内部函数需要的变量
        def 内部函数():
            引用外部变量
        return 内部函数
    
    def deco():
        x=1
        def wrapper():
            print(x)
        return wrapper
    
    wrapper=deco()
    print(wrapper)
    复制代码
    复制代码
    #包两层
    def deco1():
        y=2
        def deco():
            x=1
            def wrapper():
                print(x)
                print(y)
    
            return wrapper
        return deco
    deco=deco1()
    wrapper=deco()
    wrapper()
    复制代码

    二、无参装饰器

    1、开放封闭原则,对扩展是开放的,对修改是封闭的

    2、装饰器,装饰器本质可以任意可调用对象,被装饰的对象也可以是任意
    可调用对象,
    装饰器的功能是:
    在不修改被装饰对象源代码以及调用方式的前提下为期添加新功能

    原则:
    1.不修改源代码
    2.不修改调用方法
    目标:添加新功能

    无参装饰器=高级函数+函数嵌套

    基本框架

    #这就是一个实现一个装饰器最基本的架子
    def timer(func):
        def wrapper():
            func()
        return wrapper

    加上参数

    def timer(func):
        def wrapper(*args,**kwargs):
            func(*args,**kwargs)
        return wrapper

    加上功能

    复制代码
    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func.__name__,stop_time-start_time))
        return wrapper
    复制代码

    加上返回值

    复制代码
    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func.__name__,stop_time-start_time))
            return res
        return wrapper
    复制代码

    使用装饰器的方法一:

    复制代码
    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func.__name__,stop_time-start_time))
            return res
        return wrapper
    
    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal=timer(cal)
    cal(range(100000))
    
    运行结果:
    函数[cal],运行时间是[0.0070002079010009766]
    复制代码

    使用@装饰器名称的方法:

    复制代码
    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func.__name__,stop_time-start_time))
            return res
        return wrapper
    @timer
    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal(range(100000))
    函数[cal],运行时间是[0.007000446319580078]
    复制代码

    上课实例:

    复制代码
    #装饰器修订
    import time
    import random
    #装饰器
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
    #被装饰函数
    
    @timmer
    def index():
        time.sleep(random.randrange(1,5))
        print('welecome to index page')
    @timmer
    def home(name):
        time.sleep(random.randrange(1,3))
        print('welecome to %s HOME page' %name)
        return 1231231231
    
    index()
    
    res1=index()
    print('index return %s' %res1)
    res2=home('egon') #wraper()
    print('home return %s' %res2)
    
    
    运行结果:
    welecome to index page
    run time is 2.0001144409179688
    welecome to index page
    run time is 3.001171350479126
    index return None
    welecome to egon HOME page
    run time is 1.0000574588775635
    home return 1231231231
    复制代码
  • 相关阅读:
    中国软件技术篇
    create pdf
    我来了
    补丁号
    rdlc里面用VB语法对数值型数据进行Format
    WinForm中有些控件不能添加ToolTip关联的解决方法
    javascript弹出对话框
    省市县关联菜单
    委托与事件
    ASP.NET多文件上传方案
  • 原文地址:https://www.cnblogs.com/1204guo/p/7051168.html
Copyright © 2011-2022 走看看