Day 12 闭包函数与装饰器

Day 12

闭包函数 = 函数对象 + 函数嵌套定义 + 函数名与空间作用域

闭包函数

1、闭:指的是该函数是定义在一个函数内部的函数

2、包:指的是该函数访问了一个来自于外层函数的变量

闭包就是能够读取其他函数内部变量的函数,由于在 Python 语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成 “定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的用途:
  • 可以在函数外部读取函数内部成员
  • 让函数内成员始终存活在内存中

装饰器

1.什么是装饰器

​ 器:工具

​ 装饰:为被装饰者添加额外功能

2.为何要有装饰器

​ 一旦软件上线运行之后,就应该遵循开放封闭的原则:

​ 1、开放是指对拓展新功能的开放封

​ 2、封闭指的是对修改源码的封闭

​ 定义装饰器的目的:

​ 电话艺装饰器就是为了在遵循1和2的前提下,来为其他函数添加新的功能

​ ps:

​ 不修改被装饰对象指的是定义与调用都不能修改所以下述行为都违反了开放封闭原则:

​ 1、修改被装饰对象定义时的源代码

​ 2、修改被装饰对象的调用方式

3、如何用装饰器

​ 首先我们先写一个基本函数

import time


def SayHai(name):
    time.sleep(0.2)
	print("%s你好啊!" % name)
    
SayHai("孙悟空")

​ 现在我们要给这个函数计时,我们可以这样写

# 1									
start = time.time()
SayHai("孙悟空")
end = time.time()
print("该程序的运行时间为%s" % (end-start))

# 2
def SayHai(name):
	start = time.time()
    time.sleep(0.2)
	print("%s你好啊!" % name)
	end = time.time()
    print("该程序运行的时间为%s" % (end-start))
    
# 3    
def RunSH(name):
    start = time.time()
    time.sleep(0.2)
    SayHai(name)
    end = time.time()
    print("该程序运行的时间为%s" % (end - start))  

这两种方法都有问题,如果SayHai的函数调用次数过多,我们需要写很多的(end-start)第一种十分的不方便第二种方法虽然省了很多代码但是违背了不修改源码的原则第三种方法类似于第二种但是不灵活

​ 我们迫切的需要一种不修改源码又能为旧函数赋值新功能的方法,于是装饰器就产生了。

def timing(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        time.sleep(0.2)
        result = func(*args, **kwargs)
        end = time.time()
        print("该程序运行的时间为%s" % (end - start))
        return result

    return wrapper


sayhai = timing(SayHai)
sayhai("孙悟空")

这样一个装饰器就完成了

我们可以用更简单的方法来描述它

def timing(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        time.sleep(0.2)
        result = func(*args, **kwargs)
        end = time.time()
        print("该程序运行的时间为%s" % (end - start))
        return result

    return wrapper


@timing  
def SayHai(name):
    time.sleep(0.2)
    print("%s你好啊!" % name)
    
SayHai("孙悟空")

这里的 @timing相当于sayhai = timing(SayHai)

无参装饰器

1、无参装饰器的模板
def outter(func):
	def wrapper(*args,**kwargs):
		res=func(*args,**kwargs)
		return res
	return wrapper

前面已经定义一个无参装饰器此处不再定义

2、叠加多个装饰器
2.1 加载顺序:自下而上
2.2 执行顺序:自上而下运行内层的wrapper函数

在这里插入图片描述

有参装饰器

有参装饰器的模板:
def outter2(x,y,z,a,b):
    def outter1(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            return res
        return wrapper
    return outter1
举个栗子
def outter(engine = 'file'):
    def deco2(func2):
        def wrapper2(*args,**kwargs):
            inp_name = input('username>>>: ').strip()
            inp_pwd = input('password>>>: ').strip()
        if engine == "file":
            print('基于file的认证')
            if inp_name == "egon" and inp_pwd == "123":
                print('login successful')
                res2=func2(*args,**kwargs)
                return res2
            else:
                print('username or password error')
        elif engine == 'mysql':
            print('基于mysql的认证')
        elif engine == 'ldap':
            print('基于ldap的认证')
        else:
           print('未知的engine')
    return wrapper2
return deco2

@outter(engine='mysql')  # @deco2 # index=deco2(index)
def index(x,y):
    print('index=>',x,y)

index(1,2)  # index=>wrapper
    print('未知的engine')
return wrapper2

return deco2

@outter(engine=‘mysql’) # @deco2 # index=deco2(index)
def index(x,y):
print(‘index=>’,x,y)

index(1,2) # index=>wrapper


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值