Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器。本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等。

python中的一切都是一个对象(函数也是)

1.首先让我们来了解python中的函数嵌套

1.1

# -*- coding:utf-8 -*-
def outter():print("outter()函数里面")def inner1():return "现在在inner1()函数里面"def inner2():return "现在在inner2()里面"print (inner1())print (inner2())print ("outter执行结束")
# outter()
# outter()函数里面
# 现在在inner1()函数里面
# 现在在inner2()里面
# outter执行结束

如果像上面写的inner1和inner2将没有什么意义,没有必要在另一个函数中执行一个函数,因为完全可以用过程化实现,所以看下面

1.2.从函数内返回函数

# -*- coding:utf-8 -*-
def outter(name="inner1"):print("outter()函数里面")def inner1():return "现在在inner1()函数里面"def inner2():return "现在在inner2()里面"if name == "inner1":return inner1else:return inner2inner = outter()print(inner())
# outter()函数里面
# 现在在inner1()函数里面

1.3.函数作为参数

# -*- coding:utf-8 -*-
def inner():return "现在在inner()函数里面"
def outter(func): print("outter()函数里面")print(func())
outter(inner)
# outter()函数里面
# 现在在inner()函数里面

2.闭包:在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,并返回这个函数,那么将这个函数以及用到的一些变量称之为闭包。

2.1

def outter(num):def inner(a):print(a + num)return innerfun = outter(100)  # fun == inner
fun(1)  # 101
fun2 = outter(200)
fun2(1)  # 201
fun(2)  # 102

2.2闭包的实际用例,控制一条直线:y=ax+b,确定直线的斜率后,改变x的值获得不同的y值。

def line_slope(a, b):def line(x):return a * x + breturn lineline1 = line_slope(1, 1)
line2 = line_slope(4, 5)
print(line1(2))
print(line1(-1))
print(line2(-3))
print(line2(6))
# 3
# 0
# -7
# 29# 这个例子中,函数line与变量a,b构成闭包。在创建闭包的时候,
# 我们通过line_slope的参数a,b说明了这两个变量的取值,这样,
# 我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。
# 我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,
# 我们可以看到,闭包也具有提高代码可复用性的作用。
# 如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。
# 这样,我们就需要更多的参数传递,也减少了代码的可移植性。
# 1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
# 2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

2.3修改闭包变量。说明:Python3通过nonlocal关键字修改闭包变量,Python2通过list来修改python3中
def outter(start=0):def inner():nonlocal startstart += 1return startreturn innero1 = outter(5)
print(o1())
print(o1())o2 = outter(20)
print(o2())
print(o2())print(o1())
print(o1())print(o2())
print(o2())# 6
# 7
# 21
# 22
# 8
# 9
# 23
# 24

python2中

def outter(start=0):list1 = [start]def inner():nonlocal startlist1[0] += 1return list1[0]return innero1 = outter(5)
print(o1())
print(o1())o2 = outter(20)
print(o2())
print(o2())print(o1())
print(o1())print(o2())
print(o2())# 6
# 7
# 21
# 22
# 8
# 9
# 23
# 24

2.4LEGB 规则

# locals -> enclosing function -> globals -> builtins
a = 1  # 全局变量 globalsdef outter():a = 2  # 闭包变量 enclosingdef inner():a = 3  # 局部变量 localsprint("a=%d" % a)return innero = outter()
o()  # a=3# locals,当前所在命名空间(如函数、模块),函数的参数也属于命名空间内的变量
# enclosing,外部嵌套函数的命名空间(闭包中常见)
# globals,全局变量,函数定义所在模块的命名空间
# builtins,内建模块的命名空间。
# 在Python中,有一个内建模块,该模块中有一些常用函数;在Python启动后,
# 且没有执行程序员所写的任何代码前,Python会首先加载该内建模块到内存。
# 另外,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀,
# 其原因是对函数、变量、类等标识符的查找是按LEGB法则,其中B即代表内建模块

3.装饰器

3.1被装饰的函数无参数

import time# 定义装饰器
def log(fun):def inner():print(time.time())fun()print(time.time())return inner# 使用装饰器  @加函数名   是一种语法糖,即简写
# 真正的执行过程:send_mail = log(send_mail)  =>  send_mail = inner
@log
def send_mail():print("发送邮件")send_mail()# 1503492456.2909923
# 发送邮件
# 1503492456.2909923

3.2被装饰的函数有参数

def outter(fun):def inner(a, b):fun(a, b)return inner@outter
def add(a, b):print("a+b:%d" % (a + b))add(1, 2)
add(3, 4)
# a+b:3
# a+b:7

3.3被装饰的函数有不定长参数。

说明:把装饰器做成能装饰任何函数的装饰器,所以对于装饰器来说被装饰的函数的参数是不定长的。这样就应该用*args和**kwargs来当参数。

def outter(fun):def inner(*args, **kwargs):fun(*args, **kwargs)return inner@outter
def add(a, b, c):print("a+b+c:%d" % (a + b + c))t = (1, 2, 3)
add(*t)  # a+b+c:6
d = {"a": 1, "b": 2, "c": 10}
add(**d)  # a+b+c:13

3.4被装饰的函数有返回值。说明:一般情况下为了让装饰器更通用,可以有return。

def outter(fun):def inner(*args, **kwargs):temp = fun(*args, **kwargs)return tempreturn inner@outter
def add(a, b, c):return a + b + ct = (1, 2, 3)
ret = add(*t)
print(ret)  # 6
ret = d = {"a": 1, "b": 2, "c": 10}
print(add(**d))  # 13

3.5装饰器带参数,在原有装饰器的基础上,设置外部变量。说明:装饰器带参数的执行过程是:首先将@ 和 arg_outter(arg)分离,将arg_outter(arg)的执行结果和@结合。
def arg_outter(arg):def outter(fun):def inner():print("装饰器的参数是:%s" % arg)if arg:fun()print("我是True,我会唱歌")else:fun()return innerreturn outter@arg_outter(True)
def song():print("song")@arg_outter(False)
def listen():print("listen")song()
listen()

3.6多层装饰器的使用。说明:多层装饰器,先看第一层的装饰器,把第一层当做函数调用,函数的参数是下一层的执行结果。
 具体分析:当遇到@tag1时,发现它是一个装饰器,所以开始函数调用,即装饰谁就传谁,但是发现装饰的不是一个函数,而是一个函数外面加了一个装饰 器,意味着把tag2以及下面作为一个整体形成的结果当做参数当做tag1的参数。返回结果即第一层里面的inner函数名字。用最终装饰器的函数名字进行 接收。即link_a。所以调用link_a的时候就是调用的tag1里面的inner函数。

使用装饰器的顺序很重要,如果未按预定的顺序执行,可以更改装饰功能的整体行为。
def tag1(fun):def inner():print("<li>", end="")fun()print("</li>", end="")return innerdef tag2(f):def inner():print("<a>", end="")f()print("</a>", end="")return inner# 多层装饰器的使用
@tag1  # link_a = tag1( tag2(link_a) )
@tag2
def link_a():print("我是一个超链接", end="")link_a()  # tag1->inner()# <li><a>我是一个超链接</a></li>

3.7类装饰器(不常用)。说明:装饰器,log(say_hello),相当于一个类构造一个对象,所以把log构造成类,对象()即调用__call__()方法.

import timeclass log(object):def __init__(self, fun):self.fun = fundef __call__(self):"""当把对象当作函数进行调用时,被调用"""print(time.time())self.fun()print(time.time())@log
def say_hello():print("say_hello")say_hello()
# 1503495467.9418454
# say_hello
# 1503495467.9418454

4.装饰器的主要作用:

引入日志

函数执行时间统计

执行函数前预备处理

执行函数后清理功能

权限校验等场景缓存

Python闭包装饰器笔记相关推荐

  1. python高阶函数闭包装饰器_Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)...

    一,装饰器 装饰器:本质就是函数,功能是为其它的函数动态添加附加的功能 原则:对修改关闭对扩展开放 1.不修改被修饰函数的源代码 2.不修改被修改函数的调用方式 装饰器实现的知识储备:高阶函数,函数嵌 ...

  2. Python 进阶_闭包 装饰器

    目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...

  3. SIGIA_4P python学习 列表 字典 集合 面对对象编程 闭包 装饰器 函数式编程 作用域 异常处理

    SIGIA_4P python学习 列表 字典 集合 面对对象编程 闭包 装饰器 函数式编程 作用域 异常处理 本文连接 简介 SIGIA_4P 网址 a. 课程OKR Objectives and ...

  4. python入门day11闭包装饰器

    目录 闭包 例子 同级闭包 装饰器引入 装饰器使用 无参例子 有参例子 可变参数例子 带关键字参数的装饰器 双层装饰器 装饰器带参数 装饰器的应用 闭包 def func():a=100def inn ...

  5. Python之装饰器

    Python之装饰器 在不修改函数调用方式的前提下,也不能修改函数内部源代码!!!! 例如: 在每个季度公司发绩效,统计每个人的代码执行效率.咱们总不能是每个函数里加time模块吧. import t ...

  6. 浅谈Django的中间件与Python的装饰器

    浅谈Django的中间件 与Python的装饰器 一.原理 1.装饰器是Python的一种语法应用,利用闭包的原理去更改一个函数的功能,即让一个函数执行之前先到另外一个函数中执行其他需求语句,在执行该 ...

  7. Python的装饰器

    详解Python的装饰器 本文源码 https://github.com/tobyqin/python_decorator Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都 ...

  8. python中装饰器的作用_Python装饰器详解,详细介绍它的应用场景

    装饰器的应用场景附加功能 数据的清理或添加:函数参数类型验证 @require_ints 类似请求前拦截数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改为函数提供额外的数据 moc ...

  9. python装饰器实例-Python函数装饰器--实例讲解

    一.装饰器定义: 1.装饰器的本质为函数: 2.装饰器是用来完成被修饰函数的附加功能的 所以:装饰器是用来完成被修饰函数附属功能的函数 装饰器的要求: 1.不能修改被修饰函数的源代码: 2.不能更改被 ...

  10. python装饰器函数-Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

最新文章

  1. Java学习笔记---字符类型
  2. Ambari Server网口带宽占用率很高问题的分析和解决办法
  3. spring boot微服务通用部署启动脚本
  4. 斐波那契数列求解+尾递归
  5. properties(map)增.删.改.查.遍历
  6. Mysql 在DOS窗口下的操作
  7. ES6学习笔记03:变量的解构赋值
  8. 190517每日一句
  9. 「架构师必备」关于网络优化你必须要知道的重点
  10. window强制删除文件bat
  11. 问题 B: PIPI发工资(拓扑排序遍历)
  12. 广东工业大学化学工程考研情况
  13. 海洋地球科学开放数据库
  14. new Date在safair浏览器中不兼容
  15. 无线模块为什么要加屏蔽罩外壳?
  16. 基于可编辑DIV的带表情编辑器
  17. 2021年广西省安全员C证免费试题及广西省安全员C证考试试卷
  18. 华为5500网络限流配置_华为Eudemon 防火墙BT限流测试方案
  19. programming notes - 在线学习资源
  20. python爬取游戏数据,Python 爬虫之好游快爆游戏排行信息爬取

热门文章

  1. Sublime Text自定义插入当前时间的插件
  2. W3C-Web Service
  3. JavaEE平台学习之 01开发第一个Servlet程序
  4. pd虚拟机提示 “无法连接到 Parallels 服务” 怎么解决?
  5. Macbook使用技巧:如何在外部显示器上获得4K 60 FPS
  6. VEGAS如何分割与解组?
  7. Payload与form表单提交区别
  8. Web服务器点击劫持(ClickJacking)的安全防范
  9. 一篇关于蓝牙SDP和L2CAP协议的文章
  10. OPC UA 统一架构学习4