18_Python高级特性--闭包和装饰器

一、闭包

(1)什么是闭包?
闭包的概念就是当我们在函数内定义一个函数时,这个内部函数使用了外部函数的临时 变量,且外部函数的返回值是内部函数的引用时,我们称之为闭包。
(2)闭包再理解?
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。
(3)nonlocal关键字?
显式的指定变量不是闭包的局部变量
(4)闭包的一个常用场景就是装饰器。
(5)优点: 闭包也具有提高代码可复用性的作用

二、闭包的实际例子

def line_conf(a,b):
    def line(x):
        return a*x + b
    return line
line1=line_conf(1,1)
line2=line_conf(4,5)
print(line1(5))
print(line2(5))
#函数line与变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个变量的取值,
#这样,我们就确定了函数的最终形式(y=x+1和y=4x+5)。

在这里插入图片描述


"""
闭包需要满足的三个条件:
    1. 函数内定义一个函数
    2. 内部函数使用了外部函数的临时变量
    3. 外部函数的返回值是内部函数的引用(指的就是内部的函数名)

"""
def line_conf(a,b):
    def line(x):
        return a*x + b
    return line

line1=line_conf(1,1)
line2=line_conf(4,5)
line3=line_conf(3,2)
loopCount =100
y1 =[line1(item) for item in range(loopCount)]
y2 =[line2(item) for item in range(loopCount)]
y3 =[line3(item) for item in range(loopCount)]
## 图形绘制(pyecharts==0.5.11)===导入绘制折线图的类
from pyecharts import Line
#创建绘制折线图的对象lineObj
x =list(range(loopCount))
lineObj =Line(title="一元线性方程图形展示")
lineObj.add(name='y=x+1',x_axis=x,y_axis =y1)
lineObj.add(name='y=4x+5',x_axis=x,y_axis =y2)
lineObj.add(name='y=3x+2',x_axis=x,y_axis =y3)
#将绘制的图形显示为html文件
lineObj.render("doc/line.html")

在这里插入图片描述
在这里插入图片描述

三、装饰器(Decorator)

(1)装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的
前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,
比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。

(2)为什么需要装饰器?
写代码要遵循 开放封闭 原则,
虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
1封闭:已实现的功能代码块
2开放:对扩展开发

四、装饰器的功能

1、引入日志
2、函数执行时间统计
3、执行函数前预备处理
4、执行函数后清理功能
5、权限校验等场景
6、 缓存

五、装饰器实例

(1)无参数的函数

import time
age = 19
def is_adult(fun):
    def wrapper():
        start_time = time.time()
        if age >= 18:
            fun()
        else:
            print("未成年")
        end_time = time.time()
        print("程序运行时间:%.3f" % (end_time - start_time))

    # 返回的是函数的引用
    return wrapper
@is_adult  # 语法糖====music = is_adult(music)
def music():
    time.sleep(1)
    print("正在听音乐.....")
@is_adult
def videos():
    print("正在看视频.....")


@is_adult
def game():
    print("正在玩游戏.....")
music()

在这里插入图片描述

(2)被装饰的函数有参数

def auth(type):
    def wrapper(fun):
        def wrapper1(*args,**kwargs):
            print("当前装饰器传递的参数:",type)
            result = fun(*args,**kwargs)
            return result
        return wrapper1
    return wrapper

@auth(type='local')
def home():
    print("这是主页")

home()

在这里插入图片描述
(3)被装饰的函数有可变参数和关键字参数

(4)被多个装饰器装饰的函数

db ={
    'root':{
        'name':'root',
        'passwd':'westos',
        'is_super':0
    },
    'admin':{
        'name': 'admin',
        'passwd': 'redhat',
        'is_super': 1
    }
}
#存储当前登陆用户的信息---相当于一个缓冲区
login_user_session={}
def is_login(fun):
    def wrapper1(*args,**kwargs):
        if login_user_session:
            result = fun(*args,**kwargs)
            return result
        else:
            print("跳转登陆界面".center(50,'*'))
            user =input('User:')
            passwd =input('Passwd:')

            if user in db:
                if db[user]['passwd'] ==passwd:
                    login_user_session['username'] =user
                    print("登陆成功")

                    result = fun(*args, **kwargs)
                    return result
            else:
                print('该用户不存在')
    return wrapper1


def is_permission(fun):
    def wrapper2(*args,**kwargs):
        print("panduan permission..")
        current_user =login_user_session.get('username')
        permssion =db[current_user]['is_super']
        if permssion ==1:
            res = fun(*args,**kwargs)
            return res
        else:
            print("用户%s没有权限"%(current_user))
    return wrapper2
@is_login
@is_permission
def delete():
    return "delete Ok"

result = delete()
print(result)

在这里插入图片描述

六、通用装饰器

def decorator(fun):
    def wrapper(*args,**kwargs):  ##args,kwargs是形参
        #在调用函数之前做的操作
        result =fun(*args,**kwargs) ##*args, **kwargs是实参, *args, **kwargs是在解包
        # 在函数之后添加操作
        return result
    return wrapper
#@装饰器的名字
@decorator
def function():
    pass
#调用函数
function()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值