闭包与认识装饰器

一、函数名

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

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

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

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

#!/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')
万能装饰器

 

    

    

posted @ 2018-02-05 15:22  曹艳飞  阅读(227)  评论(0编辑  收藏  举报