zoukankan      html  css  js  c++  java
  • 闭包与认识装饰器

    一、函数名

      函数名在本质上就是函数的内存地址,函数名有以下功能:

        函数名可以赋值给别的变量;;

        函数名还可以当做容器类型里面的元素,(列表、字典);

        函数名可以当做函数的参数和返回值;具体实例如下:

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    # 函数可以赋值给别的变量
    # def func():
    #     print('caoyf')
    # a = func # 此函数名赋值给了变量'a',在下面直接输入a()就相当于调用func函数
    # a()
    
    #函数名可以当做容器类型的元素:例如:列表
    # def func():
    #     print('我是func函数')
    # def inner():
    #     print('我是inner函数')
    # def caoyf():
    #     print('我是曹艳飞函数')
    # a = [func,inner,caoyf]  # 列表的查询方式可以通过切边进行查看,为了方便查看所有结果,使用for循环一次查看所有的结果
    # for i in a:
    #     i()
    
    # 函数名可以当做函数的参数和返回值使用:
    # def func():
    #     print('func函数')
    # def inner(name):
    #     name()
    #     return name
    # a = inner(func)
    # print(a)
    函数名

    二、闭包

      函数的闭包定义:

        在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包,实例如下:

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    # 内部函数调用外部函数的变量
    # def func(a):
    #     def inner(b):
    #         return a + b # 在inner函数里面调用了func函数的变量a,然后将inner返回给调用者
    #     return  inner
    # ret = func(30)(20)
    # print(ret)
    内部函数调用外部函数的变量

        内部函数对外部函数作用域变量的引用(非全局变量),则成为内部函数为闭包,实例如下:

        判断一个函数是不是闭包,可以使用__closure__方法测试,如果打印出来的是cell那这就是一个闭包,如果打印的是None,那就不是闭包,实例如下:

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    # def func():
    #     name = 'caoyf'
    #     def inner():
    #         print(name)
    #     return inner
    # ret = func() # inner函数里面调用了func函数的变量name。
    # ret()
    # 判断是不是闭包
    # def func():
    #     name = 'caoyf'
    #     def inner():
    #         print(name)
    #     print(inner.__closure__) #这个函数是一个闭包,因为inner函数里面调用了func函数的变量name。
    #     return inner
    # ret = func()
    # ret()
    
    # def func():
    #     name = 'caoyf'
    #     def inner():
    #         print(666666)
    #     print(inner.__closure__)
    #     inner() #这个函数就不是闭包,因为内部没有引用外部的变量
    # ret = func()
    闭包与判断是不是闭包

    三、装饰器

      装饰器本质上就是一个python闭包函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

      装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

      初始装饰的形成

       现在有这么一个开发需求,领导想知道每段代码的耗时时间,来评比工作的考核

      一般开发的代码内容如下:  

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    def func():
        print('执行此段代码,你会看到意想不到的结果')

      灵机一动,写了下面的代码:

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    import time
    def func():
        start = time.time()
        time.sleep(0.1)  # 假设为执行时间,实际代码肯定不是一个print能搞定的
        print("执行此段代码,你会看到意想不到的结果")
        end = time.time()
        print('func函数共用时%s' %(end - start))
    func()
    View Code

      在接下来的几天时间里,开发的同事看见我都想打死我,我有赶紧的把原来的代码拿出来进行修改,于是又出来了下面的版本,同时告诉大家以后再使用的时候直接调用timeer函数就行了;

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    # import time
    # def func():
    #     print('执行此段代码,你会看到意想不到的结果')
    # def timeer(func):
    #     start = time.time()
    #     func()
    #     end = time.time()
    #     print('func函数共用时%s' %(start - end))
    # f1 = func
    # func = timeer
    # func(f1)
    time函数

      后来有人告诉我里面的代码还可以节俭,可以使用语法糖的方式,这样同事在计算时间的函数前加一句@timeer就可以了,于是又出了一个版本;

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    import time
    def timeer(f):
        def inner():
            start = time.time()
            f()
            end = time.time()
            print('func函数共用时%s' %(start - end))
        return inner
    @timeer
    def func():
        print('执行此段代码,你会看到意想不到的结果')
    func()
    @语法糖

      为了方便后期开发同事的使用,有修改了一次版本,增加了带有参数的和返回值的,以下是万能版本的timeer函数装饰器:

    #!/usr/bin/python
    # -*- encodeing:utf-8 -*-
    import time
    def timeer(f):
        def inner(*args,**kwargs):
            start = time.time()
            ret = f(*args,**kwargs)
            end = time.time()
            print('func函数共用时%s' %(start - end))
            return ret
        return inner
    @timeer
    def func(*args):
        print('执行此段代码,你会看到意想不到的结果 %s'%args)
    func('www.xxxooo.com')
    万能装饰器

        

        

  • 相关阅读:
    python数据库操作读书笔记
    python玩微信跳一跳实验报告
    制作自己的第一个网页
    python文件读写笔记
    Ethernet(以太网) 详解 MAC、MII、PHY
    Ethernet(以太网) 物理介质(10Base、100Base-T、100Base-TX等)
    QByteArray 转 QBitArray
    QT 线程应用
    QT release 发布打包压缩
    Qt中利用qDebug()记日志到文件
  • 原文地址:https://www.cnblogs.com/caoyf1992/p/8411265.html
Copyright © 2011-2022 走看看