前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python之函数编程(2)

Python之函数编程(2)

作者头像
AsiaYe
发布2019-11-06 15:20:31
4530
发布2019-11-06 15:20:31
举报
文章被收录于专栏:DBA随笔DBA随笔

Python之函数编程(2)

1

函数作为返回值

在Python中,可以将一个函数作为另外一个函数的返回值,举个例子:

在上面的命令中,我们定义一个return_sum()的函数,这个函数返回一个sum的函数,sum函数的作用是求一个可迭代对象的所有元素的和,当我们直接调用return_sum函数的时候,返回值f是一个函数,再次调用这个函数,我们可以得到序列的和。其中,内部的sum函数相当于引用了外部的参数,当return_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种情况在python中称之为“闭包”,需要和B-box区分开来哦。

值得注意的一点是,当我们再次调用这个return_sum函数的时候,它会重新返回一个函数f1,而这个f1和上面的f虽然都指向同一个函数,但是他们两个的值并不相等,如下:

可以看到,这两个返回函数的值并不相等,同样的,二者的调用结果互不影响。

闭包详解

从上面的例子我们可以看到,我们要想求内部函数的结果,必须重新调用那个函数f(),再来看一个例子:

上面这个例子中,我们定义了一个函数count,里面嵌套了三次循环,每次循环,都创建了一个新的函数来计算一个数字的平方值,然后,把创建的3个函数都返回了。可能我们认为它的返回值会是1,4,9,但是实际上的结果如下:

可以看到,所有的结果都是9,原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

所以得到一个约定俗成的结论:返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

再看看这个结果:

虽然这种方法能够得到最终的结果,但是思路上还是有些绕,个人不建议使用。

2

装饰器

考虑这样一种需求:我们想在函数调用前后自动打印函数日志,但是又不希望修改函数的定义,这种在代码运行期间动态增加功能的方式,就称之为“装饰器”。

在进行实验之前,首先介绍一下函数的__name__属性,每一个函数对象都有一个__name__属性,可以拿到函数的名字,下面我们举个例子说明:

当我们用一个变量f代替Python中的内置绝对值函数abs时,可以调用__name__来查看真实的函数名称。

现在我们定义一个log函数来实现上面的需求:

观察这个log函数,它是一个装饰器,它接受一个函数f作为参数,并返回一个函数wrapper,此时需要借助python的@语法(暂时不用纠结这个语法,该语法我们后续会讲到),把这个装饰器放在函数定义的地方,再去调用这个f函数,我们可以得到如下结果:

我们可以看到,将@log放到abs函数前面,相当于执行了abs=log(abs)语句,这样的操作,原来的abs函数依旧存在,只是现在的f变量指向了新的函数abs,于是调用f会直接返回log(abs)的内容。

装饰器还有更复杂的用法,这里我们不做拓展。

3

偏函数

python的functools里面还定义了很多有用的功能,其中一个就是偏函数,其实说白了和自定义函数非常像,例如我们要看看字符串‘12345’转换成整数的值,可以通过int函数来查看,但是当我们把这个‘12345’看成八进制的,怎么求对应的十进制数字呢?看看下面的例子:

但是这样的参数传递还是有些不方便,自然而然会想到如果我们定义一个int2()的函数,默认把base=2传进去,就可以直接计算二进制的数值了,functool.partial就可以帮助我们创建这样的偏函数,我们可以利用下面的方法创建一个新的函数int2:

简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:

再看一个例子,当我们传入:

max2=functools.partial(max,10)时,实际上是将10作为*args的一部分自动加到参数列表前面,如下:

我们发现在用max2函数求5,6,7的最大值的时候,直接返回10,其实是因为它相当于求

max(10,5,6,7)当中的最大值,所以结果也就可以解释了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档