重新学习完了函数,是时候将其中的一些重点重新捋一捋了,本次总结的东西只有闭包和装饰器

1.闭包

闭包是python函数中的一个比较重要功能,一般闭包都是用在装饰器上,一般学完闭包就会去学习装饰器,这俩个总是让初学时的我一脸懵逼,现在好好捋一捋。

1.1 闭包的定义

  • 内层函数对外层函数(非全局)调用
  • 闭包一般存在于内部函数
  • 闭包都是一般一层一层退出,最后退出函数外返回值
  • (自我理解)函数外部对于函数内部的调用以及对内部函数的值调用

1.2 闭包的判断

__closure__的使用

####不是闭包
name = 'test'
def func():
def inner():
print(name)
return inner()
f = func()
print(f.__closure__[0].cell_contents)
#结果
TypeError: 'NoneType' object is not subscriptable
#结果就是没有闭包调用的值,就不是闭包 #是闭包
def func():
name = 'test'
age = 18
def inner():
print(name)
print(age)
return inner
f = func()
print(f.__closure__[0].cell_contents)
print(f.__closure__[1].cell_contents)
#结果
18
test

1.3 闭包的机制

在编译器中碰到函数,在函数执行结束后会将名称空间关闭,不过对于闭包,内部机制是碰到闭包的空间就不会关闭,在一段时候不在调用或者使用后才会关闭

1.4 闭包的使用以及使用场景

用闭包的形式写一个数字的连加

def func(i):
num = 1 def inner():
nonlocal num
num += i
print(num) return inner
f = func(3)
for i in range(5):
f()

上面这个只是一个很简单的功能,对于闭包在一些日常的使用场景有

装饰器和爬虫的一部分使用

2.装饰器(一个需求引发的血案)

需求:公司内一个项目运营了一段时间,TeamLeader觉得现在的代码执行效率有点低下,需要对现有函数的的执行效率进行一次测试。

2.1 直接调用

在最开始的时候没想完整,只是实现功能,代码如下

import time
def func1():
print('func1')
time.sleep(0.5) def func2():
print('func2')
time.sleep(0.6) def test(f):
stat_time = time.time()
f()
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time)) test(func1)
test(func2)
#结果
func1
执行效率为0.5010201930999756
func2
执行效率为0.6002087593078613

对于这个,你的领导绝对想要杀了你,这样的话打乱了整个项目的函数调用顺序,测试一遍,全部的函数基本没法用了,需要改进,改进目的是减少对于已有函数的影响

2.2 一定的伪装

import time
def func1():
print('func1')
time.sleep(0.5) def func2():
print('func2')
time.sleep(0.6) def test(f):
stat_time = time.time()
f()
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time)) f = func1
func1 =test
func1(f)
f1 = func2
func2=test
func2(f1)
#结果和上面一致

和最开始的那个版本相比呢,有一定的伪装了,可是执行的方式和以前就不一样了,还有一个比较重要的是这样执行函数不能传参数,项目的函数之间调用一定是有参数的,所以这个版本也PASS了,继续想吧,下个阶段实现的目的是执行函数和以前一致

2.3 比较好的伪装

def test(f):
def inner():
stat_time = time.time()
f()
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time))
return inner
#结果
func1
执行效率为0.5008118152618408

不太好理解,借用老师上课的一张图,有空了在去做动图吧

这个版本已经和非常接近完整版了,不过python中有语法糖的功能,可以将上述函数尽量减少

2.4 伪装成功-装饰器

看一下代码

import time

def test(f):
def inner():
stat_time = time.time()
f()
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time))
return inner
@test
def func1():
print('func1')
time.sleep(0.5)
@test
def func2():
print('func2')
time.sleep(0.6) func1()
func2()

看一下这个@test就是这个小老鼠,装饰器加上下面的函数名,就自动生成一个装饰器,这样就看着很顺眼了,不过还有一些功能啊,有些函数还是有一些参数需要传参,貌似现在的功能还没有实现哎,在改改吧。

2.5 装饰器的传参

既然传参,那么参数的数量就不一致,这样就需要动态传参了,看代码

import time

def test(f):
def inner(*args,**kwargs):
stat_time = time.time()
f(*args,**kwargs)
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time))
return inner
@test
def func1(x):
print(x)
time.sleep(0.5)
@test
def func2(x,y):
print(x,y)
time.sleep(0.6) func1('a')
func2('b',[1,2,3,4])
#结果
a
执行效率为0.5004942417144775
b [1, 2, 3, 4]
执行效率为0.6011292934417725

2.6 装饰器的返回值

上面那个应该是已经非常非常接近于完全体了,即使是函数,有了传参,那么就有返回值,那么返回值怎么才能看到呢,代码如下

import time

def test(f):
def inner(*args,**kwargs):
stat_time = time.time()
r1 =f(*args,**kwargs)
end_time = time.time()
print('执行效率为%s'%(end_time-stat_time))
return r1
return inner @test
def func1(x):
print(x)
time.sleep(0.5)
return 666
@test
def func2(x,y):
print(x,y)
time.sleep(0.6)
return 333 print(func1('a'))
print(func2('b',[1,2,3,4]))
#结果
a
执行效率为0.5004842281341553
666
b [1, 2, 3, 4]
执行效率为0.6007628440856934
333

写到现在才终于把整个迭代器搞明白了,哎,以后的工作就是伴随着装饰器啊

2.7 装饰器的总结

对上述所有的迭代器总结下就是下面这个例子了

def test(f):
def inner(*args,**kwargs):
#对函数进行装饰之前的代码
ret = f(*args,**kwargs)#返回值
#对函数进行装饰之后的代码
return ret#将函数的返回值返回出去
return inner
#装饰器的基本结构就是这个啦。。。
装饰器:装饰器的本质是闭包,而且装饰器其实就是个函数而已。
装饰器:在不改变原函数调用方式上,给原函数增加了一些额外的功能。登录验证,写日志,执行效率等等。

3.延伸:代码开发的开放封闭原则

开放封闭原则:
对拓展开放的:
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。
所以我们必须允许代码扩展、添加新功能。
对修改是封闭的:
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,
如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器就是开放封闭原则完美的体现。

python中的闭包和装饰器的更多相关文章

  1. 21.python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...

  2. Python 中的闭包与装饰器

    闭包(closure)是函数式编程的重要的语法结构.闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性. 如果在一个内嵌函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内嵌函数 ...

  3. 轻松理解python中的闭包和装饰器 (下)

    在 上篇 我们讲了python将函数做为返回值和闭包的概念,下面我们继续讲解函数做参数和装饰器,这个功能相当方便实用,可以极大地简化代码,就让我们go on吧! 能接受函数做参数的函数我们称之为高阶函 ...

  4. 轻松理解python中的闭包和装饰器(上)

    继面向对象编程之后函数式编程逐渐火起来了,在python中也同样支持函数式编程,我们平时使用的map, reduce, filter等都是函数式编程的例子.在函数式编程中,函数也作为一个变量存在,对应 ...

  5. 聊聊Python中的闭包和装饰器

    1. 闭包 首先我们明确一下函数的引用,如下所示: def test1(): print("--- in test1 func----") # 调用函数 test1() # 引用函 ...

  6. python中的闭包与装饰器

    #原创,转载请留言联系 装饰器的本质就是闭包,所以想知道装饰器是什么,首先要理解一下什么是闭包. 闭包 1. 外部函数返回内部函数的引用.2. 内部函数使用外部函数的变量或者参数. def outer ...

  7. python中函数总结之装饰器闭包

    1.前言 函数也是一个对象,从而可以增加属性,使用句点来表示属性. 如果内部函数的定义包含了在外部函数中定义的对象的引用(外部对象可以是在外部函数之外),那么内部函数被称之为闭包. 2.装饰器 装饰器 ...

  8. python基础16_闭包_装饰器

    不了解是否其他语言也有类似 python 装饰器这样的东西. 最近才发现ECMAScript6也是有生成器函数的,也有 yield  generator 装饰器的基础知识是闭包: # 闭包:嵌套函数, ...

  9. 第十七篇 Python函数之闭包与装饰器

    一. 装饰器 装饰器:可以拆解来看,器本质就是函数,装饰就是修饰的意思,所以装饰器的功能就是为其他函数添加附加功能. 装饰器的两个原则: 1. 不修改被修饰函数的源代码 2. 不修改被修饰函数的调用方 ...

随机推荐

  1. CentOs~程序部署那些事

    永久更新中…… 主要说一下在centos里,在安装程序和监控程序时,用到的一些常用的命令,希望可以帮到大家! 远程安装程序包:yum install 程序包名 下载程序包:wget 程序包地址 解压t ...

  2. WebApi系列~不支持put和delete请求的解决方法

    回到目录 原因 由于安装了webDAV模块引起的,在web.config里的system.webserver节点,将webdav模块移动 将http请求的权限开放 实现 <system.webS ...

  3. 前端笔记之JavaScript(十二)缓冲公式&检测设备&Data日期

    一.JavaScript缓冲公式ease 原生JS没有自己的缓冲公式,但是你要自己推理的话,必须要懂一些数学和物理公式: 让div用100毫秒(帧),从left100px的位置变化到left800px ...

  4. PE知识复习之PE文件空白区添加代码

    PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...

  5. Linux常用监控命令简介 – vmstat,ps,free,uptime 等

    vmstat [-a] [-n] [delay [ count]]vmstat [-f] [-s] [-m]vmstat [-S unit]vmstat [-d]vmstat [-p disk par ...

  6. 在win10系统开启linux子系统

    1. 2.重启计算机 3.在winstore下载和安装 ubuntu 4.查看当前win10子系统的linux版本 lsb_release -a 5.设置root账号密码, 在终端输入命令 sudo ...

  7. 如何使用Dubbo 2.7.0和Spring boot实现FAT测试(Feature Acceptance Test)

    在一个调用链非常长的功能中,如果想修改其中的一个特性,并进行测试,而又不影响该环境的其他用户使用现有功能.特性,例如: 1. A.B.C.D之间通过Dubbo实现远程调用 2. 这些模块可能有一个或者 ...

  8. Linux CentOS开机启动项设置命令:chkconfig

    1.开机启动+++crontab 定时执行(定时执行可参考:https://www.cnblogs.com/prefectjava/p/9399552.html)可实现自动化运行的目的,简化了维护人员 ...

  9. Python re 模块

    Python re 模块 TOC 介绍 作用 正则表达式语法 贪婪和非贪婪 普通字符和特殊字符 分组(比较重要) re modul level 方法 正则表达式对象 匹配对象 常用例子 注意事项 Ja ...

  10. rxjava切换线程避免重复代码

    .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThrea ...