Python闭包装饰器笔记
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闭包装饰器笔记的更多相关文章
- python 闭包@装饰器
1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...
- python闭包&装饰器&偏函数
什么是闭包? 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的 ...
- python 闭包&装饰器(一)
一.闭包 1.举例 def outer(): x = 10 def inner(): # 内部函数 print(x) # 外部函数的一个变量 return inner # 调用inner()函数的方法 ...
- Python之装饰器笔记
概述: 用于管理和增强函数和类行为的代码 提供一种在函数或类定义中插入自动运行代码的机制 特点 更明确的语法.更高的代码可维护性.更好的一致性 编写 函数基础: 将函数赋给变量.将函数作为参数传递. ...
- 【Python】 闭包&装饰器
python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...
- Python 进阶_闭包 & 装饰器
目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...
- python 3.x 的装饰器笔记
今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
随机推荐
- About darwin OS
Darwin 是一种Unix-like操作系统,整合数种的技术,包含开 Darwin LOGO 放原始码的XNU核心,一种以微核心为基础的核心架构来实作Machkernel.操作系统的服务和userl ...
- 小知识:匿名类和lambda有什么区别?
我只发现了关于this的区别: 匿名类的this,是指匿名类的实例对象. lambda的this,是指外部类的实例对象. 测试代码如下: /** * Created by LarryZeal on 2 ...
- 第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制
第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制 用命令创建自动爬虫文件 创建爬虫文件是根据scrap ...
- Eclipse/MyEclipse上配置Spring环境
在MyEclipse上配置Spring环境 myeclipse其实已经集成Spring的开发环境,我们只需在新建的项目上添加spring的配置环境就可以 新建一个java项目 选中创建好的项目之后,在 ...
- Git -- 从远程库克隆
上次我们讲了先有本地库,后有远程库的时候,如何关联远程库. 现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆. 首先,登陆GitHub,创建一个新的仓库,名字叫gitskill ...
- 【Access-Control-Allow-Origin】跨域问题
[前言] 在实际项目中,可能是多个项目共同完成某个功能,他们之间需要实现数据的交互.这样就会需要有跨域的问题. 比如,发布在不同电脑上的不同项目之间,用不同语言开发的项目之间…… [JSONP] 当使 ...
- [NSURL URLWithString:] returns nil
You need to escape the non-ASCII characters in your hardcoded URL as well: //localisationName is a a ...
- 如何能延长windows server 2008 R2激活期 .
当windows server 2008 R2使用已经到期的时候,要求激活,我们可以通过以下命令,延长激活期. 在运行中输入:slmgr.vbs -rearm 重新启动windows server 2 ...
- 周期性调度器scheduler_tick
周期性调度器由中断实现,系统定时产生一个中断,然后启动周期性调度器,周期性调度器执行过程中要关闭中断, 周期性调度器执行完毕后再打开中断(handle_IRQ_event, IRQF_DISABLE ...
- Unity判断网络是否连接以及判断是否连接WiFi
由于项目中的核心模块需要用到网络连接,所以需要首先检测用户是否有网络百度了下,有人说通过连接自己的服务器进行测试的,也有人说通过延迟来判断的最后发现原来Unity是提供了网络判断的方法的.Networ ...