首页 > 编程语言 > 详细

13、python中的函数(闭包与装饰器)

时间:2018-06-22 22:32:21      阅读:174      评论:0      收藏:0      [点我收藏+]

一、嵌套函数

      函数的内部又再定义另一个函数,这个函数就叫嵌套函数,里面含函数就叫内部函数。

示例:

技术分享图片

 

二、返回函数

      函数可以接收函数对象作为参数,同理函数也能返回一个函数对象作为返回值。

示例:

技术分享图片

返回函数可以用来延迟函数的执行。

 

三、命名空间与变量作用域

      变量作用域指的是变量的存活的范围。命名空间指的是属于一个对象的所有属性(对象)的集合。

示例:

技术分享图片

A的命名空间是A函数对象里面的所有对象的集合,包括变量a、函数B、变量b;B的命名空间就是属于函数B的所有对象的集合,包括变量b;

a的变量作用域就是A的命名空间,b的变量作用域就是B的命名空间。

可以看出,命名空间就是对象的下一层的全部空间(比如A的命名空间就是A的下一层全部空间),变量作用域就是变量所处层的上一层对象的命名空间(比如a的作用域就是A的命名空间)。

 

四、闭包

      一个嵌套函数的内部函数使用了内部函数以外的变量,这个嵌套函数就叫闭包。

示例:

技术分享图片

闭包给我们一个重要的提示是,一个变量只要在作用域里面,它可以在内部函数中发挥作用。

 

五、装饰器

      装饰器本质是一个函数,是一个返回函数的高阶函数,也是一个闭包。装饰器能解决的问题是:在一个原函数功能不变的情况下,为这个原函数增加一些新的功能。

比如说有一个打印我的名字的函数myname:

技术分享图片

现在想在不改变myname的代码的情况下打印i come from foshan,这样就用到装饰器了:

技术分享图片

事实上,我们不需要内部函数也可以为传入函数添加功能的:

技术分享图片

这样做的话如果我们传入的func带有参数就用不了了,我们还可以这样:

技术分享图片

这样的话虽然能传入带有参数的func,但新增加的功能与func的调用分开,这样也不妥。

所以我们的装饰器应该是集接收函数、返回函数、闭包为一身的函数,而且允许传入的函数带参数:

技术分享图片(*args,**kw)参数组表示可以传入任意的参数。

 

六、装饰器操作符@

      定义了装饰器之后,我们就可以拿装饰器去应用在任意我们想增加相应功能的函数了:

技术分享图片

为了使装饰器使用起来时更方便,主要为了代码看上去逻辑更清晰明了,于是便定义了@能直接调用参数,具体用法如下:

技术分享图片

在函数定义前声明了@wherefrom这个语句后,在函数调用时就会执行一下逻辑:

myname = wherefrom(myname)

 

七、高级装饰器

       我们在定义装饰器时,原函数是不能更改的。如果我们新增加的功能中还要网里面传入新参数,这种装饰器该怎么定义?思路很简单,本来两层的嵌套函数我们写够三层就可以了,第一层用于传入新参数,第二层用于传入函数:

技术分享图片(注意:这里的aplace和func传入的顺序不能改变,请想一下为什么。)

测试一下效果:

技术分享图片

这里执行逻辑是:

myname = wherefrom("guangzhou")(myname)

 

八、装饰后的函数名字问题

      无论是普通装饰器还是高级装饰器,在用了@这个操作符装饰函数后,在调用被装饰函数的时候,其函数名指向的具体的函数对象已经不是原来的函数对象了,就像上面的:myname = wherefrom(myname) 和 myname = wherefrom("guangzhou")(myname) 一样,函数名都指向了inner这个函数对象:

技术分享图片

但有时候我们后续程序里可能会用调用到原函数的名字,如上面的myname.__name__这样,为了避免发生混淆,我们应该在装饰器定义时考虑这个事情:

技术分享图片

 

我们在inner函数的代码毫无改动的情况下,把inner函数的名字指向了func函数的名字,所以我们能不能把这种新增功能定义成一个装饰器,用来提供给其他的装饰器定义时使用呢?python内部已经帮我们实现了这种功能:

技术分享图片

functools中的wraps装饰器就是专门做这个的。有兴趣的可以看看wraps的源代码,看这个装饰器怎么实现的。

 

具体参考:

1、《核心编程第二版》第11章;

2、廖雪峰 - 函数式编程

 

——————本篇完!

13、python中的函数(闭包与装饰器)

原文:https://www.cnblogs.com/lqxing1994/p/9202745.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!