闭包:

  就是内层函数对外层函数(非全局变量的)非全局变量的引用

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----------闭包 、装饰器的更多相关文章

  1. Python闭包装饰器笔记

    Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器.本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等. python中的一切都是一个对象(函数也是) 1.首 ...

  2. python 闭包@装饰器

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

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

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

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

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

  5. 【Python】 闭包&装饰器

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

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

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

  7. Python各式装饰器

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

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

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

  9. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  10. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

随机推荐

  1. mongo 语法 增删改查

    1.增 db.collection.insert()与db.collection.save() 都是增加,区别:save()遇到相同_id后,则更新此_id数据. 而insert()则报错 > ...

  2. 【es6】let和const

    let 1.不存在变量提升      es5中var和function都存在变量提升,但let声明的变量不存在.     在代码块内,使用let命令声明变量之前,该变量都是不可用的.这在语法上,称为“ ...

  3. 大数据搭建各个子项目时配置文件技巧(适合CentOS和Ubuntu系统)(博主推荐)

    不多说,直接上干货! 很多同行,也许都知道,对于我们大数据搭建而言,目前主流,分为Apache 和 Cloudera 和 Ambari. 后两者我不多说,是公司必备和大多数高校科研环境所必须的! 分别 ...

  4. 关系型数据库MySQL多实例

    简介 MySQL数据库是一个中小型关系型数据库管理系统,软件开发者为瑞典MySQL AB公司.在2008年1月16号被Sun公司收购后Sun公司又被oracle公司收购.目前MySQL被广泛地应用在I ...

  5. 解决SSH连接linux时长时间不操作自动断开

    最近重装Linux系统,但是这次ssh连接云服务区Linux系统时,经常出现一段时间不操作,连接自动中断,表现为光标还在闪动,但是却无法操作.只好关闭终端,重新连接,很是麻烦. 为此,通过网络查找,找 ...

  6. JVM启动报错: Could not reserve enough space for object heap error

    首先了解一下参数的含义: 参数 含义 -Xms2G -Xmx2G 代表jvm可用的heap内存最小和最大 -XX:PermSize -XX:MaxPermSize 代表jvm的metadata内存的大 ...

  7. CSS小技巧(一)

    左右布局 将内部的子元素加浮动,父元素清除浮动即可. 代码: <!DOCTYPE html> <html> <head> <title>test< ...

  8. Lambda表达式&匿名方法

    “Lambda表达式“(lambda Expression)就是一个匿名函数(匿名方法),lambda表达式基于数学中的入演算得名. lambda运算符:所有的lambda表达式都是用新的lambda ...

  9. DateReader读取数据

    DateReader对象提供了用循序的.只读的方式读取Command对象获取的数据结果集正是因为DateReader是以循序的方法连续地读取数据,所以DateReader会以独占的方式打开数据库连接. ...

  10. Android Viewpage 滑块

    依赖: implementation 'com.android.support:appcompat-v7:28.0.0' 在主页面layout <android.support.v4.view. ...