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 inner1
else:
return inner2 inner = 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 inner fun = outter(100) # fun == inner
fun(1) #
fun2 = outter(200)
fun2(1) #
fun(2) #

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

def line_slope(a, b):
def line(x):
return a * x + b return line line1 = line_slope(1, 1)
line2 = line_slope(4, 5)
print(line1(2))
print(line1(-1))
print(line2(-3))
print(line2(6))
#
#
# -7
# # 这个例子中,函数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 start
start += 1
return start return inner o1 = outter(5)
print(o1())
print(o1()) o2 = outter(20)
print(o2())
print(o2()) print(o1())
print(o1()) print(o2())
print(o2()) #
#
#
#
#
#
#
#

python2中

def outter(start=0):
list1 = [start] def inner():
nonlocal start
list1[0] += 1
return list1[0] return inner o1 = outter(5)
print(o1())
print(o1()) o2 = outter(20)
print(o2())
print(o2()) print(o1())
print(o1()) print(o2())
print(o2()) #
#
#
#
#
#
#
#

2.4LEGB 规则

# locals -> enclosing function -> globals -> builtins
a = 1 # 全局变量 globals def outter():
a = 2 # 闭包变量 enclosing def inner():
a = 3 # 局部变量 locals
print("a=%d" % a) return inner o = 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 temp return inner @outter
def add(a, b, c):
return a + b + c t = (1, 2, 3)
ret = add(*t)
print(ret) #
ret = d = {"a": 1, "b": 2, "c": 10}
print(add(**d)) #
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 inner return 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 inner def 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 time

class log(object):
def __init__(self, fun):
self.fun = fun def __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 闭包@装饰器

    1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...

  2. python闭包&装饰器&偏函数

    什么是闭包? 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的 ...

  3. python 闭包&装饰器(一)

    一.闭包 1.举例 def outer(): x = 10 def inner(): # 内部函数 print(x) # 外部函数的一个变量 return inner # 调用inner()函数的方法 ...

  4. Python之装饰器笔记

    概述: 用于管理和增强函数和类行为的代码 提供一种在函数或类定义中插入自动运行代码的机制 特点  更明确的语法.更高的代码可维护性.更好的一致性 编写 函数基础: 将函数赋给变量.将函数作为参数传递. ...

  5. 【Python】 闭包&装饰器

    python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...

  6. Python 进阶_闭包 & 装饰器

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

  7. python 3.x 的装饰器笔记

    今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...

  8. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  9. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

随机推荐

  1. 关于Unity中如何立即中断动画然后重新开始播放

    今天做一个FPS游戏的时候,用的是新版的动画系统,遇到一个问题. 就是用枪打敌人的时候,敌人会播放一个被击中的动画,但是如果在动画播放的过程中再射击敌人,敌人会先把第一个被击中的动画播放完,才再播放第 ...

  2. mxnet卷积计算

    #coding:utf-8 ''' 卷积计算 ''' import mxnet as mx from mxnet.gluon import nn from mxnet import ndarray a ...

  3. 嵌入式开发之uart---rs232 和rs485 和rj45和usb简介

    (1) profilebus和can(control控制器局域网)和hub(集线器) (uart)通用异步传输 rs232: ibm 提出的,两根线,按位bit传输,是端到端的单信号电平模式,理论上有 ...

  4. IE8不支持数组的indexOf方法

    在IE8下有个js错误,但是在其它浏览器下(Firefox, Chrome, IE9)下面都很正常.后来调试发现原因是在IE8下,js数组没有indexOf方法. 在使用indexOf方法前,执行一下 ...

  5. zabbix 配置SNMP监控

    什么是SNMP? 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组 ...

  6. Linux中mkdir和touch命令区别

    一.目的 本文将介绍linux下新建文件或文件夹.删除文件或文件夹命令.         touch能够新建文件,mkdir用来新建文件夹.rm用来删除文件或文件夹.         本文将选取ubu ...

  7. 全新WayOS 配置文件保存工具支持蓝色界面路由版本

    一直以来都有群里的朋友要求我弄一个支持蓝色界面路由的参数备份工具,也一直拖了大半年 昨天忙到4点多,早上又因为一些小的BUG被用户电话叫起,干脆就帮你们整一个这个工具了 功能还是一样,支持各种参数的保 ...

  8. MBProgressHUD 第三方库使用

    关键操作:   效果如下:   ViewController.h #import <UIKit/UIKit.h> #import "MBProgressHUD.h" @ ...

  9. webpack学习简单总结

    webpack使用总结: 入门使用: 这个报错说明需要安装相应的Loader,并在引用时指定相应的loader 执行成功如图: chunk指相应的区块. 要是css引入正确:必须引入css-loade ...

  10. Java进阶面试题列表

    面向对象编程的基本理念与核心设计思想 解释下多态性(polymorphism),封装性(encapsulation),内聚(cohesion)以及耦合(coupling). 继承(Inheritanc ...