代码改变世界

第十一天

2018-03-30 20:49  dalao说得对  阅读(133)  评论(0编辑  收藏  举报

今天主要学了俩东西(我觉得):

  1、闭包

    闭包是指,子函数用到了父函数的变量。概念是这个,但具体有什么用,不是很理解。现在学到的好像也只用于了

装饰器,也就是用于调用内部函数,望以后的知识或实践可以弥补这个空缺。

    当形成一个闭包时,系统会开辟一个内存用来储存这些数据(无法修改只能调用),所以作用应该是方便调用

    下面是老师的博客的资料,作为参考资料:

def func():
    name = '太白金星'
    def inner():
        print(name)

闭包函数:

内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数
#函数内部定义的函数称为内部函数

 

由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!

我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

是不是直接就把这个函数的名字返回就好了?

这才是闭包函数最常用的用法

复制代码
def func():
    name = 'eva'
    def inner():
        print(name)
    return inner

f = func()
f()
复制代码

判断闭包函数的方法__closure__

复制代码
#输出的__closure__有cell元素 :是闭包函数
def func():
    name = 'eva'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()
复制代码
闭包嵌套
闭包函数获取网络应用

  2、语法糖  @函数名(加在需要被检测的函数的上面)

  上课时老师用的例子是讲检测程序的运行时间,需要调用到warpper中的inner函数。

所谓的语法糖,我认为就是当需要一段代码执行且是在别的函数里执行时,会遇到这种操

作,就像一颗空芯的棒棒糖,糖心则是需要被检测且运行的程序。

# def timmer(f):  # f = func1 函数名

#     def inner(*args,**kwargs):
#         start_time = time.time()
#         f(*args,**kwargs)
#         time.sleep(0.3)
#         end_time = time.time()
#         print('此函数的执行效率%s' % (end_time - start_time))
#     return inner
#
# @timmer  # func1 = timmer(func1) # inner
# def func1(a,b):
#     print(a,b)
#     print('你有病呀,领导,测试我的执行效率干甚。')

这是上课时用到的例子

  也就是说当需要检测func1()运行使用的时间时,需要用到timmer下的inner程序,此时需要用到语法糖,

或者可以用  f = func1

       func1 = timmer

       func1(f)    代替(为了什么,难道只是保持前后一致达到满足视觉的享受吗)

  总之就是用来在函数的子函数中调用外部函数的一种操作吧,可能一层一层拨皮容易搞混,才发明了这个语法糖的东西(确实很好用)

日后应补充实战经验。

老师的参考资料:

  

一,什么是装饰器?

 

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

 

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

 

二,装饰器的形成过程。

 

现在我有一个需求,我想让你测试这个函数的执行时间,在不改变这个函数代码的情况下:

 

import time

def func1():
    print('in func1')

def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

func1 = timer(func1)
func1()
装饰器---简单版

 

但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都得func1 = timer(func1)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,graph,等等,所以更简单的方法,python给你提供了,那就是语法糖。

 

import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer   #==> func1 = timer(func1)
def func1():
    print('in func1')


func1()
装饰器---语法糖

 

 刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

 

def timer(func):
    def inner(a):
        start = time.time()
        func(a)
        print(time.time() - start)
    return inner

@timer
def func1(a):
    print(a)

func1(1)

装饰器——带参数的装饰器
装饰器---带参数的装饰器

 

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print('in func1')

@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func1('aaaaaa','bbbbbb')
print(func2('aaaaaa'))
装饰器---hold住所有参数的装饰器

 

上面的装饰器已经非常完美了,但是有我们正常情况下查看函数信息的方法在此处都会失效:

 

复制代码
def index():
    '''这是一个主页信息'''
    print('from index')

print(index.__doc__)    #查看函数注释的方法
print(index.__name__)   #查看函数名的方法
复制代码

 

如何解决呢?

 

复制代码
from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)
print(index.__name__)
复制代码

 

三,开放封闭原则。

 

1.对扩展是开放的

 

    为什么要对扩展开放呢?

 

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

 

  2.对修改是封闭的

 

    为什么要对修改封闭呢?

 

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

 

装饰器完美的遵循了这个开放封闭原则。

 

四,装饰器的主要功能和固定结构。

 

def timer(func):
    def inner(*args,**kwargs):
        '''执行函数之前要做的'''
        re = func(*args,**kwargs)
        '''执行函数之后要做的'''
        return re
    return inner
装饰器的固定格式

 

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper
装饰器的固定格式--wraps版

 

五,带参数的装饰器。

 

假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

 

一个一个的取消掉? 没日没夜忙活3天。。。

 

过两天你领导想通了,再让你加上。。。

 

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''执行函数之前要做的''')
            re = func(*args,**kwargs)
            if flag:
                print('''执行函数之后要做的''')
            return re
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()
带参数的装饰器

 

六,多个装饰器装饰一个函数。