闭包和装饰器是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装饰器的更多相关文章

  1. Python函数编程——闭包和装饰器

    Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...

  2. python之闭包与装饰器

    python闭包与装饰器 闭包 在函数内部定义的函数包含对外部的作用域,而不是全局作用域名字的引用,这样的函数叫做闭包函数. 示例: #-------------------------------- ...

  3. 关于python的闭包与装饰器的实验

    首先看闭包,在嵌套函数内添加返回值,可以通过外部函数读取内部函数信息 #encoding=utf-8 #闭包应用 #先定义闭包函数,并使用 def outer(func): def inner(): ...

  4. python中闭包和装饰器

    前言: 编程语言发展的过程中,我们为了提高代码利用率,发明了函数式编程.函数将代码封装起来,我们需要用到此功能函数的时候,调用一下就可以了.但是使用的过程中,也遇到了一些问题,比如函数实现的功能不够, ...

  5. python的闭包与装饰器

    原文发表在我的博客主页,转载请注明出处 前言 如果把python当作脚本语言,每次就是写个几十行上百行来处理数据的话,装饰器也许不是很必要,但是如果要开发一个大型系统,装饰器是躲不开的,最开始体会ry ...

  6. Python的闭包和装饰器

    什么是闭包 python中函数名是一个特殊的变量,它可以作为另一个函数的返回值,而闭包就是一个函数返回另一个函数后,其内部的局部变量还被另一个函数引用. 闭包的作用就是让一个变量能够常驻内存. def ...

  7. Python高级--闭包与装饰器

    前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能.如权限认证. 一.如何定义闭包 1.闭包就是两个嵌套的函数,外层函数 ...

  8. python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

  9. Python作用域-->闭包函数-->装饰器

    1.作用域: 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我要理解两点:a.在全局不能访问到局部 ...

随机推荐

  1. 小白学 Python 爬虫(7):HTTP 基础

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  2. Netty学习篇⑥--ByteBuf源码分析

    什么是ByteBuf? ByteBuf在Netty中充当着非常重要的角色:它是在数据传输中负责装载字节数据的一个容器;其内部结构和数组类似,初始化默认长度为256,默认最大长度为Integer.MAX ...

  3. /etc/security/limits.conf 详解与配置

    目录 一. /etc/security/limits.conf 详解 /etc/security/limits.conf 配置解析 /etc/security/limits.d/ 目录 二. ulim ...

  4. MySQL(学生表、教师表、课程表、成绩表)多表查询

    1.表架构 student(sid,sname,sage,ssex) 学生表 course(cid,cname,tid) 课程表 sC(sid,cid,score) 成绩表 teacher(tid,t ...

  5. 关于Go defer的详细使用

    先抛砖引玉defer的延迟调用:defer特性: . 关键字 defer 用于注册延迟调用. . 这些调用直到 return 前才被执.因此,可以用来做资源清理. . 多个defer语句,按先进后出的 ...

  6. 【Android - IPC】之Serializable和Parcelable序列化

    1.序列化的目的 (1)永久的保存对象数据(将对象数据保存到文件或磁盘中): (2)通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的,因此序列化的目的是将对象数据 ...

  7. LNMP 源码发布Thinksaas论坛

    第一步:搭建LNMP架构 LNMP架构 注意:搭建php服务时,初始化 ./configure --prefix=/usr/local/php5 \ --enable-fpm \ --enable-d ...

  8. Linux中docker的使用二

    容器下安装jdk和tomcat:通过挂载文件的方法,把宿主机上的文件挂载到容器中,然后解压到opt目录下:tar -zxvf 包名 -C /opt//opt目录下drwxr-xr-x 8 10 143 ...

  9. 深入 .NET Core 基础 - 1:deps.json, runtimeconfig.json 以及 dll

    深入 .NET Core 基础:deps.json, runtimeconfig.json 以及 dll 原文地址:https://natemcmaster.com/blog/2017/12/21/n ...

  10. Linux下搭建及配置禅道服务器详细过程-包含软件资源

    **1:百度云盘下载: ** 禅道--链接: https://pan.baidu.com/s/1Stu7nOZVIPO5TnpJWjWtiQ 提取码:dnik CentOs操作系统--链接: http ...