Python之闭包and装饰器
闭包和装饰器是Python中非常重要的一种语法格式,在日常工作中应用非常广泛。
首先,我先为大家简单的介绍一下闭包的概念。
闭包:闭包是在函数嵌套的基础上,内层函数使用到外层函数的变量,且外层函数返回内层函数的引用的一种语法格式。
闭包的基本格式,代码实现:
def outer():
num = 0
def inner():
# 使用外部函数的变量
print(num)
return inner # 返回inner函数在内存空间中的地址 # 将outer函数的返回值赋值给变量f,也就是说将f指向outer函数中的inner函数的内存地址
f = outer()
# 调用inner函数
f()
我们学习闭包的作用,其实就是为了学习装饰器。
那么,我们先来了解一下什么是装饰器。
装饰器就是通过闭包来对指定的函数进行功能的扩充,装饰器在函数定义时就会执行。
装饰器的特点:
1.不修改指定修饰函数的代码,
2.不修改指定修饰函数的调用方式,
3.给指定修饰函数增加相应的功能。
装饰器的种类:
1.普通装饰器
普通装饰器就是闭包语法格式的基础上,满足装饰器的特点的一种语法格式。
普通装饰器的代码实现:
def decorator(func):
# 此时func指向的是show函数
def inner(*args,**kwargs):
# 装饰的代码
ret = func()
return ret
return inner @decorator # 原理为 show = decorator(show)
# 此时show指向的是decorator函数中的inner函数
def show():
print('show run....') # 此时相当于调用decorator函数中的inner函数,并函数的返回值赋值给ret
ret = show()
图示如下:
1.1 多个装饰器装饰同一个函数:
多个装饰器装饰同一个函数的执行过程,先执行距离需要装饰函数近的装饰器,然后在执行距离需要装饰函数远的装饰器。
通过代码实现:
def make_div(func):
"""对被装饰的函数的返回值 div标签"""
# func指向是p中的inner函数的内存空间地址
def inner():
return "<div>" + func() + "</div>"
return inner def make_p(func):
"""对被装饰的函数的返回值 p标签"""
# func 指向的是content函数的内存空间地址
def inner():
return "<p>" + func() + "</p>"
return inner # 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
# 当执行make_div的语法糖时,传递的是make_p中的inner函数的内存空间地址
@make_div
# make_div相当于装饰make_p修饰后的函数
@make_p # 按照顺序从下向上依次装饰,其根据是装饰器只能装饰已有函数# 当执行make_p的语法糖时,传递的是connet函数的内存空间地址
def content():
# content指向是p中的inner函数内存空间地址
return "人生苦短"
result = content()
print(result)
代码解读:
@make_div
@make_p
def show():
pass
执行流程:
1.@make_p装饰show函数
2.@make_div装饰@make_p修饰后的函数也就是make_p中的inner函数
2.类装饰器
类装饰器就是通过一个类来装饰函数,相较于普通装饰器,类装饰器可以使用父类中的方法。
类装饰器的代码实现:
class Decorator(object):
# 使用init方法来接收需要装饰的函数
def __init__(self, func):
# func指向show函数所在的内存空间地址
# 使用__func指向需要装饰的函数的内存空间地址
self.__func = func # 可以让类的对象通过对象名()的方式被调用
def __call__(self, *args, **kwargs):
# 此时相当于调用了show函数
ret = self.__func(*args, **kwargs)
return ret @Decorator # 原理是 show = Decorator(show)
# 此时show指向的是Decorator类的对象的内存地址
def show():
print('show run .....') # 此时表示Decorator对象被调用,并接受show函数的返回值
ret = show()
在以上代码中,类中的init方法就相当于闭包中的外层函数用来接收被装饰的函数,call方法就相当于闭包中内层函数用来编写装饰代码以及调用被装饰的函数。
图示如下:
3.带有参数的装饰器
带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式: @装饰器(参数,...)
代码实现:
# 设置路由表,将字典当做路由表
router ={} def set_args(url):
# url 传递的参数
def set_func(func):
# func --> show方法的内存空间地址
def inner():
func()
# 将inner函数的内存空间地址添加到路由表中
# key = url
# value = inner函数的内存空间地址
router[url] = inner
# 返回inner函数的内存空间地址
return inner
# 返回set_func函数的内存空间地址
return set_func # 装饰器在函数定义时就会执行 # 1.先执行set_args('/show.html'),
# 相当于先调用set_args函数并进行参数的传递,
# 最后得到set_args的返回值也就是set_func
# 2.在执行@运算符,相当于执行装饰器@set_func
# @set_func --> show = set_func(show)
# 此时show ---> set_args.set_func.inner
@set_args('/show.html')
def show():
print('show run ....') def error():
print('error run....') def browser(url):
func = error
if url in router:
func = router[url]
# func()相当于调用了字典中符合条件的函数
func() if __name__ == '__main__':
browser('/show.html')
代码解读:
@set_args('/show.html')
def show():
pass
其中@set_args('/show.html'),按照运算符优先级应该先执行()也就是先执行set_atgs('/show.html'),然后再执行@运算符。
执行流程是:
1.先执行set_args('/show.html'),相当于调用set_args()函数,并进行传参;
2.接受set_args()函数的返回值,并结合@运算数(@set_func),对show函数进行装饰。
重点代码的执行流程图解:
Python之闭包and装饰器的更多相关文章
- Python函数编程——闭包和装饰器
Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...
- python之闭包与装饰器
python闭包与装饰器 闭包 在函数内部定义的函数包含对外部的作用域,而不是全局作用域名字的引用,这样的函数叫做闭包函数. 示例: #-------------------------------- ...
- 关于python的闭包与装饰器的实验
首先看闭包,在嵌套函数内添加返回值,可以通过外部函数读取内部函数信息 #encoding=utf-8 #闭包应用 #先定义闭包函数,并使用 def outer(func): def inner(): ...
- python中闭包和装饰器
前言: 编程语言发展的过程中,我们为了提高代码利用率,发明了函数式编程.函数将代码封装起来,我们需要用到此功能函数的时候,调用一下就可以了.但是使用的过程中,也遇到了一些问题,比如函数实现的功能不够, ...
- python的闭包与装饰器
原文发表在我的博客主页,转载请注明出处 前言 如果把python当作脚本语言,每次就是写个几十行上百行来处理数据的话,装饰器也许不是很必要,但是如果要开发一个大型系统,装饰器是躲不开的,最开始体会ry ...
- Python的闭包和装饰器
什么是闭包 python中函数名是一个特殊的变量,它可以作为另一个函数的返回值,而闭包就是一个函数返回另一个函数后,其内部的局部变量还被另一个函数引用. 闭包的作用就是让一个变量能够常驻内存. def ...
- Python高级--闭包与装饰器
前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能.如权限认证. 一.如何定义闭包 1.闭包就是两个嵌套的函数,外层函数 ...
- python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)
转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...
- Python作用域-->闭包函数-->装饰器
1.作用域: 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我要理解两点:a.在全局不能访问到局部 ...
随机推荐
- 《HelloGitHub》第 44 期
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...
- JavaScript笔记十二
1.DOM对CSS的操作 - 读取和修改内联样式 - 使用style属性来操作元素的内联样式 - 读取内联样式: 语法:元素.style.样式名 - 例子: 元素.style.width 元素.sty ...
- 手动模拟实现Spring IOC功能(基于javaConfig风格)
以下文中spring特指spring frameWork项目,不含其它:如spring cloud等. 作为刚开始研究spring源码的小白,对于spring两大核心功能之一的IOC,虽说大致了解了B ...
- warning: rpmts_HdrFromFdno: Header V4 DSA/SHA1 Signature, key ID XXXXXX: NOKEY
我在使用Centos时,会出现这种错误: 本人实践有效的办法是: 加上"--nogpgcheck"参数 就是在你要执行的语句后面加上该参数就行了! 我当时是为了安装jenkins时 ...
- mysql 基础知识整理
什么是MySQL? MySQL 是一种关系型数据库,在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展.阿里巴巴数据库系统也大量用到了 MySQL,因此它的稳定性是有保障的. ...
- C语言I作业09
问题 回答 这个作业属于哪个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/SE2019-2/homework/10032 我在 ...
- LeetCode 5282. 转化为全零矩阵的最少反转次数
地址 https://leetcode-cn.com/submissions/detail/39277402/ 题目描述给你一个 m x n 的二进制矩阵 mat. 每一步,你可以选择一个单元格并将它 ...
- 基于JDK1.8的JVM 内存结构【JVM篇三】
目录 1.内存结构还是运行时数据区? 2.运行时数据区 3.线程共享:Java堆.方法区 4.线程私有:程序计数器.Java 虚拟机栈.本地方法栈 5.JVM 内存结构总结 在我的上一篇文章别翻了,这 ...
- ajax请求成功,状态却是200
AJAX状态为200,这类状态代码表明服务器成功地接受了客户端请求.简单的来说成功发送一个AJAX请求,但是就是不进入success事件,进入error事件. $.ajax({ type:'POST' ...
- #化鲲为鹏,我有话说# 鲲鹏弹性云服务器配置 Tomcat
在鲲鹏弹性云服务器上配置 Tomcat 1 下载 Tomcat 地址 :http://tomcat.apache.org/ 根据需要选择版本,这里使用 Tomcat 9,下载压缩包 2 将文件发送到服 ...