闭包和装饰器是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. mr的partition分区

    1.Partitioner 组件通过让 Map 对 Key 进行分区,从而将不同分区的 Key 交由不同的 Reduce 处理.Partition属于map端 2.分区的总数与任务的reduce任务数 ...

  2. spring boot 一个项目启动多个实例

    0.前言 在开发中,我们经常需要以不同端口启动同一个项目的多个实例,IDEA中启动多个实例很简单 1.方法 1.1.在项目中,选择编辑配置,然后点选允许并行运行,如下图: 1.2.调出RunDashb ...

  3. Ubuntu中git pull远程仓库时显示403错误

    # 报错内容 fatal: unable to access 'https://git.dev.tencent.com/chendongnan/sfedu_wx.git/': The requeste ...

  4. JavaEE基础(02):Servlet核心API用法详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.核心API简介 1.Servlet执行流程 Servlet是JavaWeb的三大组件之一(Servlet.Filter.Listener) ...

  5. MVVMLight绑定数据

    我们先新建一个WPF项目MVVMLightDemo,添加GalaSoft.MvvmLight.dll(没有可以自己下载) 然后在项目中添加三个文件夹,如图: 先添加我们的Model,在Model下新建 ...

  6. 一道题反映Java的类初始化过程

    Java的类初始化过程: 1. 父类的static成员变量,static语句块. 2. 子类的static成员变量,static语句块. 3. 父类的普通成员变量,构造函数. 4. 子类的普通成员变量 ...

  7. 压缩感知重构算法之OLS算法python实现

    压缩感知重构算法之OMP算法python实现 压缩感知重构算法之CoSaMP算法python实现 压缩感知重构算法之SP算法python实现 压缩感知重构算法之IHT算法python实现 压缩感知重构 ...

  8. mac版 sublime快捷键大全

    按这几大类分类:文件 编辑 选择 查找 视图 去往 工具 项目 窗口 帮组一.文件cmd + N 新建文件cmd + S 保存文件cmd + shift + S 文件另存为cmd + alt + S ...

  9. Statistics : Data Distribution

    1.Normal distribution In probability theory, the normal (or Gaussian or Gauss or Laplace–Gauss) dist ...

  10. NIO-Channel接口分析

    目录 NIO-Channel源码分析 目录 前言 接口 SCTP协议 UDP协议 TCP协议 文件 总结 相关文献 NIO-Channel源码分析 目录 NIO-概览 NIO-Buffer NIO-C ...