闭包和装饰器

一,闭包

内部的函数引用了外部函数的变量

def f1(b):
    def f2():
        print(b)  #内部函数引用了外部函数的变量b
    f2()

f1()

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

直接就把这个函数的名字返回就好了。

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

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

判断闭包函数的方法__closure__

 判断是否为闭包函数

闭包的嵌套

复制代码
def wrapper():
    money = 1000
    def func():
        name = 'alex'
        def inner():
            print(name,money)  #alex 1000
        return inner
    return func

f = wrapper()
i = f()
i()
复制代码

内部函数返回一个值到全局

复制代码
def f1():  #从内部函数返回一个值到全局
    b = 10
    def f2():
        return b
    return f2()

print(f1())  #10
复制代码

闭包函数获取网络应用

 

from urllib.request import urlopen
def get(url):
    return urlopen(url).read()
print(get('http://www.cnblogs.com/weiwu1578/articles/7772732.html'))

 

二,装饰器

装饰器的作用
在不改变函数的调用方式的情况下,给函数的前后添加新的功能

装饰器的形成过程

简单版

关于时间

复制代码
import time    #模块
def timmer(func):
    def inner():
        start_time = time.time()  #程序起始时间
        time.sleep(1)        #程序休停时间
        func()
        end_time = time.time()  #程序结束时间
        print('=====%s=====' % (end_time - start_time))
    return inner

def func():
    print('老铁666老铁')

func = timmer(func)
func()

结果:  老铁666老铁
    =====1.0008132457733154=====

复制代码

 

装饰器----语法糖,万能的装饰

复制代码
def timmer(qqxing):   #timmer是装饰器的名字,传入的参数就是被装饰的函数
    def inner(*args,**kwargs):      #在装饰器中需要定义一个内部函数
        print('调用func之前')
        ret = qqxing(*args,**kwargs)      #被装饰的函数,并且要执行
        print('调用func之后')
        return ret
    return inner      #将内部函数的名字返回

@timmer   #语法糖  func = timmer(func)
def func(name):
    print('%s老铁666'%(name))
    return 1111111111

ret = func('俊杰')
print('result : %s'%ret)
结果

  调用func之前
  俊杰老铁666
  调用func之后
  result : 1111111111

复制代码

总结:

  装饰器的本质:一个闭包函数

  装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

装饰带参数的函数:

复制代码
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'))
结果:

  in func1
  0.0
  in func2 and get a:aaaaaa
  0.0
  fun2 over

复制代码

装饰带参数且有返回值的函数

复制代码
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   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func2('bbbbb')
print(func2('aaaaaa'))
结果:

  in func2 and get a:bbbbb
  in func2 and get a:aaaaaa
  fun2 over

复制代码

开放封闭原则

  1.对扩展是开放的

    为什么要对扩展开放呢?

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

  2.对修改是封闭的

    为什么要对修改封闭呢?

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

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

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

装饰器的主要功能:

在不改变函数调用方式的基础上在函数的前、后添加功能。

装饰器的固定格式:

复制代码
def timer(func):
    def inner(*args,**kwargs):
        '''执行函数之前要做的'''
        re = func(*args,**kwargs)
        '''执行函数之后要做的'''
        return re
    return inner
复制代码

有成千上万个函数使用了一个装饰器,把这些装饰器都取消掉

复制代码
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()
复制代码
posted on 2019-05-08 18:17  斜阳红红  阅读(125)  评论(0编辑  收藏  举报