python----------闭包 、装饰器
闭包:
就是内层函数对外层函数(非全局变量的)非全局变量的引用
def func():
name = '老人家'
def func1():
print(name)#局部变量对全局变量的引用 因为并没有在这个函数总定义name只是在它的父级定义了
return func1
func()()
闭包函数:
内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数
#函数内部定义的函数称为内部函数
为什么使用闭包:
闭包的使用就是开辟一个不是立刻关闭的空间
因为我们的函数每当执行完就会关闭这个函数 ,但是如果我们的是个嵌套函数,我们执行完父级的过程了 但是子函数中的内容还没有执行,这个时候该怎么办呢? 这个时候就可以使用闭包让父级函数不能立刻关闭
进而可以让我们马上使用子函数中的内容
def func():#定义一个父级函数
name='eva'
def inner():#在这个父级函数中再定义一个子函数 #这个子函数从它的开始到它的结束就是整个闭包
print(name) #这个是引用父级函数内的变量name #使用闭包就是防止父级函数使用完之后不能使用子函数了 所以我们就定义一个闭包 然后让父级函数不能立刻关闭 进而调用子函数
#
return inner #为了让我们能使用子函数就把子函数的名字给返还出去
f= func()
f()
闭包的整个过程就是在内存中开辟一个空间这个空间并不是父级函数执行完之后就会立刻关闭的,一般的都是函数执行是开辟一个空间然后执行完之后就关闭 闭包个并不是这个样 这个是在内存中,开辟一个不是立刻关闭的空间然后当父级执行完 又可以让子函数在这个空间内执行,然后执行完等许久不用了 python的回收机制就会把这个内存给回收了
检测闭包:
我们也可以检测这个函数是不是属于闭包
判断闭包函数的方法__closure__
name = 'alex'
def func(): def Aveo():
print(name)#这时候这个name引用的不是父级的变量了是全局变量了 所以就不是闭包了
Aveo()
print(Aveo.__closure__) #这个必须是这个写在子函数的结束位置 才能测试
func()
def fun(name):
#其实这里省略了一部name = 'hhh' #送一子函数还是引用了父函数的内容 那么就是闭包
def func1():
print(name)
func1()
print(func1.__closure__) #在子函数的结束检测子函数是不是闭包
fun('hhh')
闭包函数的嵌套:
def wrapper():
money =100
def func():
name= 'eva'
def inner():
print(name,money)
return inner
return func
f= wrapper()#这一步就是子函数f=func
i =f() #i = inner
i()
闭包的面试题:
name = '老南华'
def wraaper(n):
#这里相当于省略了一个n=name='老南华'
def inner():
print(n)
inner()
print(inner.__closure__)
wraaper(name)
函数的装饰器:
装饰器本质上是一个Python函数,它可以让其它函数在不做任何变动的情况下增加额外功能,装饰器的返回值也是一个函数对象。他经常用于有切面需求的场景。比如:插入日志,性能测试,事务处理,缓存,权限校验等。有了装饰器我们就可以抽离出大量的与函数功能无关的雷同代码进行重用。
其实函数的名字也是特殊的变量 所以函数名是可以进行传递的
# 函数名是函数的名字,本质:变量,特殊的变量。
# 函数名() 执行此函数。
什么是装饰器:
在不改变原函数的执行的情况下,为原函数增加额外的功能
import time #因为是测试代码的运行时间的 所以一就需要导入时间模块 def func1():
print('你想干什么 还想测试我')
# 我们来做一个测试一个函数的功能就是测试这个函数的效率的
def timmer(f):
def inner():#在嵌套一个函数
start_time = time.time() #开始时间
f()
time.sleep(0.3) #因为你做的是测试一个函数的运行效率但是代码在计算机中运行快的 几乎不可见,那么我们就需要加个让它延迟3秒的功能就是调用sleep然后延迟0.3秒
end_time=time.time() #结束时间
print('此函数的执行效率%s'%(end_time-start_time))
return inner #把这个函数名返回给父级以便于调用 f = timmer(func1)
f()
大家可以看到我们最后的赋值操作需要几步 那么如果我们再定义其他的修改的功能呢 ?就需要再定义新的功能再重新赋值吗?不 我们为了简化操作就定义了魔法糖
魔法糖的运用
import time def wraaper(f):
def inner():
start_time = time.time() #开始时间
f()
time.sleep(0.4) #为了防止此程序太快计算机看不到 我们就让它延迟0.3秒
end_time=time.time()
print('此函数的执行效率%s' % (end_time - start_time))
return inner
@ wraaper #大家看魔法糖的运用 就是在要测试的函数上定义一个@魔法符号 然后让它加上执行测试功能的函数的名称即可 def func():
print('就是你要测试我啊')
func()
被装饰函数带参数的装饰器:
import time
def timmer(f): # f = func1 函数名
def inner(*args,**kwargs):
start_time = time.time()
f(*args,**kwargs)
time.sleep(0.3)
end_time = time.time()
print('此函数的执行效率%s' % (end_time - start_time))
return inner @timmer # func1 = timmer(func1) # inner
def func1(a,b):
print(a,b)
print('你有病呀,领导,测试我的执行效率干甚。')
func1(1,2) #进行传递参数
格式:
def wrapper(func):
def inner(*args,**kwargs):
'''被装饰函数之前'''
ret = func(*args,**kwargs)
'''被装饰函数之后'''
return ret
return inner @wrapper
def func(a,b):
pass
return 566
print(
func(*args,**kwargs)
)
如果你要查找你的函数中的名字和函数内的注释内容就可以用__name__ 和__doc__来表示
@wrapper
def func(*args):
print(666)
return args
print(func(*[1,2,3]))
def wrapper():
pass
def func1():
'''
此函数是完成登陆功能,参数分别是...作用
:return:
'''
print(6666)
# print(func1.__name__)
print(func1.__doc__)
return True
func1()
print(func1.__name__)
print(wrapper.__name__)
多个参数的装饰器
import time
def timmer(*args,**kwargs):
def wrapper(f):
def inner(*args,**kwargs):
if flag:
start_time = time.time()
ret = f(*args, **kwargs)
time.sleep(0.3)
end_time = time.time()
print('此函数的执行效率%f' % (end_time - start_time))
else:
ret = f(*args, **kwargs)
return inner
return wrapper flag = True
@timmer(flag,2,3) # 两步:1,timmer(flag) --> wrapper 2,@wrapper 装饰器
def func1():
print(666)
@timmer(flag)
def func2():
print(333) func1()
func2()
带参数的装饰器的意思就好比 你的装饰器 其实就是来查看 100个不同函数的执行时间的 那么有一天 你突然不想查看了 那你难道还一一去修改吗 ,这个时候就凸显了带参数的装饰器的意义了,
你可以让装饰器含有参数 然后把装饰器的参数给修改掉就可以了 比如你在外面传递的是flag的所以那么你就只需要更改flag的值就可以了
带参数的装饰器的运行流程

多个装饰器修饰一个函数 主要是为多个一个函数赋予不同的功能
def wrapper1(func):
def inner1(*args,**kwargs):
print(111)
func(*args,**kwargs)
print(222)
return inner1
def wrapper2(func):
def inner2(*args,**kwargs):
print(333)
func(*args,**kwargs)
print(4444)
return inner2
@wrapper2 #里面的f==inner1 外面的f == inner2
@wrapper1 #里面的f==函数名f 外面的f == inner1
def func ():
print('主函数')
func()
保留被装饰过后的函数原信息:functools
import functools
因为被装饰过的后的函数的名字信息都成了装饰器内部的inner函数了 所以我们要要取被装饰过的函数的原信息就很难了,我们要取被装饰过后的函数的原名字什么的就需要用到functools
def wrapper(self, func):
@functools.wraps(func) #让你传递进来的函数保留原名称和原信息
def inner(request,*args, **kwargs):
self.request = request
return func(request,*args, **kwargs)
python----------闭包 、装饰器的更多相关文章
- Python闭包装饰器笔记
Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器.本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等. python中的一切都是一个对象(函数也是) 1.首 ...
- python 闭包@装饰器
1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...
- python闭包&装饰器&偏函数
什么是闭包? 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的 ...
- python 闭包&装饰器(一)
一.闭包 1.举例 def outer(): x = 10 def inner(): # 内部函数 print(x) # 外部函数的一个变量 return inner # 调用inner()函数的方法 ...
- 【Python】 闭包&装饰器
python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...
- Python 进阶_闭包 & 装饰器
目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- python 基础——装饰器
python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
随机推荐
- Jquery 在多个相同标签click的问题
最近在做文章的删除动作,用Jquery来执行操作.但是实现时一开始总是只能对第一个起作用,其他的点击删除后没反应. 一开始的jquery代码是这样的, $('#articledelete').on(' ...
- spring之IOC模拟实现
使用Spring框架已经有很长时间了,一直没有仔细的想过框架的设计思想是什么样的,底层到底是怎么实现的,这几天调试程序看了些源码,写下来做个记录.由于Spring框架博大精深,个人理解的难免有不正确的 ...
- Mozilla新特性只支持https网站,再次推动SSL证书普及
Mozilla的官方博客2015.4.30正式宣布了淘汰HTTP的方案. 其中包括:设定一个日期,所有的新特性将只提供给HTTPS网站:HTTP网站将逐步被禁止访问浏览器功能,尤其是那些与用户安全和隐 ...
- 设计模式应用场景之Model设计中可以用到的设计模式
在开发中,不同的场景适用不同的设计模式.对于开发建模方面,可以根据模型的抽象类型设计成简单属性模式和复杂组合模式. 因为组合模式中的属性为多种类型对象,可操作性也比较灵活. 而针对这种复杂数据结构,有 ...
- [CPP] Big Three
前言 上一篇攻略中,我们已经充分理解了不带指针的类的设计原则,并且还从标准库设计大师的作品里收获了不少功力.而这一篇攻略,将继续完成基于对象的类的关卡,解决这一关的最后一个问题,那就是带指针的类.在这 ...
- Nginx Open File Cache
Nginx 的 open_file_cache 相关配置可以缓存静态文件的元信息,在这些静态文件被频繁访问时可以显着提升性能. 被缓存的文件元信息包括: fd,文件被打开一次后,fd保留使用 size ...
- CSS3动画积累+动画库+3d动画
一.animates.css animate.css是来自dropbox的工程师Daniel Eden开发的一款CSS3的动画效果小类库.包含了60多款不同类型的CSS3动画,包括:晃动,闪动,各种淡 ...
- Grid控件
Grid控件是WPF布局容器中功能最强大.最灵活的控件.Grid控件基本上能够完成其他WPF容器控件所能完成的功能,Microsoft建议大多数界面的布局都使用Grid控件来实现,因此默认情况下.vs ...
- Java - 谨慎实现Comparable接口
类实现了Comparable接口就表明类的实例本身具有内在的排序关系(natural ordering). 因此,该类可以与很多泛型算法和集合实现进行协作. 而我们之需要实现Comparable接口唯 ...
- C# 之多线程(二)
一.确定多线程的结束时间,thread的IsAlive属性 在多个线程运行的背景下,了解线程什么时候结束,什么时候停止是很有必要的. 案例:老和尚念经计时,2本经书,2个和尚念,一人一本,不能撕破,最 ...