IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python闭包装饰器学习笔记[2021/9/18]中秋补班了吗lol -> 正文阅读

[Python知识库]Python闭包装饰器学习笔记[2021/9/18]中秋补班了吗lol

闭包和装饰器
嗨,周六中秋补班,是不是在期待假期呢?然而有些人请假了,觉得很无聊,在家里写笔记了
话不多说,走起~

什么是闭包

 一个能记住嵌套作用域变量值的函数,尽管作用域已经不存在。这种语言现象称之为闭包:

例如函数f1结束了,但是f2仍然能记住x=88;这种情况下,嵌套函数内部会用到外部的变量x。
在这里插入图片描述

什么是装饰器

python语言中,可将函数作为参数传入一个装饰函数,返回另外一个被装饰了的函数;在这个过程中我们对函数添加新的功能;装饰器本身是一个函数或者类;

在学习装饰器的时候,执行以下代码的结果,不是预期的那样,我怀疑自己写错了

import logging
def use_logging(func):
    def wrapper():
        logging.info("%s is running" % func.__name__)
        return func
    return wrapper
@use_logging
def foo():
    print("This is foo")
foo()

执行的结果是 空,于是乎,开始调试代码。在网上找到了以下代码,原来内层的函数需要返回的是函数的调用;
在这里插入图片描述
另外,将上述代码return wrapper 改为 return wrapper(),也会返回报错;原因是@use_logging的语法糖,就是相当于foo = user_logging(foo)。
显然,当执行函数时,装饰器函数就已经调用wrapper函数了,相当于调用func(),此时会执行func,返回值为空;如果return wrapper(),则多了一次函数调用,空类型是无法调用的;报错如下:
在这里插入图片描述
所以正确的装饰器代码如下:

def use_logging(func):
    # print("装饰器嵌套层外")
    def wrapper():
        # logging.info("%s is running" % func.__name__)
        print("%s is running" % func.__name__)
        return func()  # 这里需要是个可调用的函数
    return wrapper 
@use_logging  # foo = user_logging(foo)
def foo():
    print("This is foo")
foo()		# 执行函数foo前,会先执行装饰器

** 以下是带参数的装饰器:**

def use_logging(func):
    def wrapper(name):	# 装饰器返回的函数引用,且可以将函数的参数传入内层函数,形参名称可任意
        print("%s is running" % func.__name__)
        print("decorate %s is running" % name)
        return func(name) 
    return wrapper
@use_logging  # foo = user_logging(foo)
def foo(name):
    print("This is %s" % name)
foo(2) 

带参数的装饰器,且函数的参数名称可以和内层函数的参数名称不一致:

def use_logging(func):
    def wrapper(AGE):
        print("%s is running" % func.__name__)
        print("decorate %s is running" % AGE)
        return func(AGE)  # 这里需要是个可调用的函数
    return wrapper
@use_logging  # foo = user_logging(foo)
def foo(name):
    print("This is %s" % name)
foo(2)

装饰器的执行顺序:
一个函数还可以同时定义多个装饰器,比如:

@a
@b
@c
def f ():
    pass

它的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于
f = a(b(c(f)))

例如

def a(func):
    def wrapper():
        print('iner %s is running' % a.__name__)
        return func()
    return wrapper
def b(func):
    def wrapper():
        print('iner %s is running' % b.__name__)
        return func()
    return wrapper
def c(func):
    def wrapper():
        print('iner %s is running' % c.__name__)
        return func()
    return wrapper
@b
@a
def foo():
    print("foo is running")
foo()

执行结果为:
iner b is running
iner a is running
foo is running

代码注释:
多层的装饰器,相当于foo = b(a(foo)) ,函数执行从外到里,装饰器自下而上;内层返回的是a的wrapper的引用,但是并未执行;
b(wrapper_a)返回的是b的wrapper的引用,但是未执行;当执行foo()时,会执行b_wrapper,相当于执行b中的func(),此时b的func已经被装饰,即为wrapper_a。
相当于先打印a内的一句话,再执行原函数func(打印一句话)

另外,由于先调用装饰器a,在调用装饰器b,所以会先打印a中外层的语句;例如:

def a(func):
    print("outer a")
    def wrapper():
        print('iner %s is running' % a.__name__)
        return func()
    return wrapper
def b(func):
    print("outer b")
    def wrapper():
        print('iner %s is running' % b.__name__)
        return func()
    return wrapper
@b
@a
def foo():
    print("foo is running")
foo()

执行结果就是:
outer a
outer b
iner b is running
iner a is running
foo is running

装饰器的应用

装饰器经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。(此处转载 https://foofish.net/python-decorator.html - 理解 Python 装饰器看这一篇就够了)

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:56:01  更:2021-09-19 07:56:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 16:29:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计