函数(闭包函数,装饰器)

闭包函数

1.什么是闭包函数。

定义在函数内部的函数,这个内部函数引用了外部函数变量。

2.为什么要用闭包函数。

保存局部信息不被销毁,保证数据的安全性

3.怎么使用闭包。

例子:

# 例一:
def wrapper():
    a = 1
    def inner():
        print(a)
    return inner
ret = wrapper()
​
# 例二:
a = 2
def wrapper():
    def inner():
        print(a)
    return inner
ret = wrapper()
​
​
# 例三:
def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a,b)

这三个例子都是闭包函数

给函数传参数值有两种方式:

  1.普通的传参

def index1(username):
     print(username)

  2.闭包

def outter(x,y):
    def my_max():
        if x>y:
            return x
        return y
    return my_max
res =outter(1,40)
res1 = outter(10,3)

4.那么闭包函数可以做哪些事情呢?

  1.可以保存一些非全局变量但不易被销毁,改变的数据

  2.装饰器

下面我们就引入了装饰器

装饰器

1.什么是装饰器。

就是给被装饰对象加上新的功能。在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。

2.为什么要使用装饰器。

这里我们要解释一个新名词,开放封闭原则。

开放封闭原则:
  开放:对扩展开放
  封闭:对修改封闭

3.如何使用装饰器

首先我们按照之前的知识写一下,统计index函数执行的时间

import time
def index():
    time.sleep(3)
    print('index.....')
start = time.time()
index()
end = time.time()
print('index 执行了%s' %(end-start))

修改一下上面代码,将统计时间用函数包装一下。装饰器简单版本

import time
def index():
    time.sleep(3)
    print('index..................')

def outtere(func):
    def get_time():
        start = time.time()
        func()
        end = time.time()
        print('run time:%s',%(end-start))
    return get_time
index = outter(index)
index()

如果我们的Index函数有参数呢,我们可以继续改进一下(无参函数和有参函数都可以直接调用,可以接收任意数量的参数)

import time
def index(name):
    time.sleep(3)
    print('%s hello' %name)

def outter(func):
    def get_time(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)
        end = time.time()
        print('run time:%s'%(end-start))
        return res
    return get_time

index = outter(index)
index('zzp')

index = outter(index)这句话是不是我们每次在装饰函数时都要这样写?现在有一种很简便的写法

语法糖在书写的时候应该与被装饰对象紧紧挨着
两者之间不要有空格

import time

def outter(func):
    def get_time(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)
        end = time.time()
        print('run time:%s'%(end-start))
        return res
    return get_time

@outter    #index = outter(index)
def index(name):
    time.sleep(3)
    print('%s hello' %name)

index('zzp')

装饰器的模板

def outter(func):
    def inner(*args,**kwargs):
        print('执行被装饰函数之前 你可以做的操作')
        res = func(*args,**kwargs)
        print('执行被装饰函数之后 你可以做的操作')
        return res
    return inner

带参数的装饰器

def login_auth2(data_source):
    # data_source = 'file'
    def login_auth(func):
        # func = index
        def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应
            if user_dic['is_login']:
                res = func(*args, **kwargs)
                return res
            else:
                if data_source == 'file':
                    username = input('please input your username>>>:').strip()
                    password = input('please input your password>>>:').strip()
                    if username == 'jason' and password == '123':
                        user_dic['is_login'] = True
                        res = func(*args,**kwargs)
                        return res
                    else:
                        print('username or password error')
                elif data_source == 'MySQL':
                    print('from MySQL')
                elif data_source == 'ldap':
                    print('ldap')
                else:
                    print('暂无该数据来源')
        return inner
    return login_auth
@login_auth2('file')
def index():
  print('.....')
index()

这里的@login_auth2('file') 相当于  index = login_auth(index) 

叠加多个装饰器(**)

  1.加载顺序(outter函数的调用顺序)自下而上

  2.执行顺序(wrapper函数的执行顺序)自上而下

def outter1(func1): #func1=wrapper2的内存地址
    print('加载了outter1')
    def wrapper1(*args,**kwargs):
        print('执行了wrapper1')
        res1=func1(*args,**kwargs)
        return res1
    return wrapper1

def outter2(func2): #func2=wrapper3的内存地址
    print('加载了outter2')
    def wrapper2(*args,**kwargs):
        print('执行了wrapper2')
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2

def outter3(func3): # func3=最原始的那个index的内存地址
    print('加载了outter3')
    def wrapper3(*args,**kwargs):
        print('执行了wrapper3')
        res3=func3(*args,**kwargs)
        return res3
    return wrapper3



@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
    print('from index')

index()
万般皆下品,唯有读书高!
原文地址:https://www.cnblogs.com/s686zhou/p/11170560.html