Python快速编程入门——第7章 高级函数

作者 : 郭然 本文共3385个字,预计阅读时间需要9分钟 发布时间: 2020-05-2 共386人阅读

第7章 高级函数

一、闭包
二:装饰器
三:常见Python的内置函数

一、闭包

如果一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数就会被称为闭包。闭包必须满足如下三个条件:
(1)存在于嵌套关系的函数中。
(2)嵌套内部函数引用了外部函数的变量。
(3)嵌套的外部函数会将内部函数名作为返回值返回

def outer(start=0):
count = [start] #函数内的变量
#内部函数
def inner():
count[0]+=1 #引用外部函数的变量
return count[0]
#返回内部函数的名称
return inner()
quote = outer(5)
print(quote)
#结果:6

二:装饰器

内裤可以用来遮羞,但是到了冬天没法为我们御寒,聪明人发明了长裤,有了长裤后就不会再冷了。装饰器就像这里说的长裤,在不影响内裤的作用的前提下,给我们的身体提供了保暖的效果。

什么是装饰器
装饰器本质是一个Python函数,它可以在不改动其他函数的前提下,对函数的功能进行扩充。通常情况下,装饰器用于下列场景:
(1)引入日志
(2)函数执行时间统计
(3)执行函数前预备处理
(4)执行函数后清理
(5)权限校验
(6)缓存
先看一个简单的例子

def test_one():
print('test_one')

现在有一个需求,希望可以输出函数的执行日志,这时,有人会这么实现:

def test_one():
print('test_one')
print('test_one is running')
test_one()

但是,如果函数test_two()、函数test_three()都有类似的需求,那么现在这样的做法会出现大量重复的代码。为了减少重复的代码,我们可以创建一个新的函数专门记录函数执行日志,谁需要记录执行日志,就把谁作为参数传递,如下:

def print_log(func):
print('函数正在运行中')
func()
def test_one():
print('test_one')
print_log(test)

按照上述代码将函数作为参数传递,虽然可以实现功能,但是却破坏了原有代码的逻辑结构。如果要求一键实现的函数,不能修改,只能扩展,即遵守“封闭开放”原则,那么是不允许在函数test内部进行修改的。
装饰器可以满足上述需求。在Python中,装饰器的语法是以@开头,下面我们写一个简单的装饰器。

def wrap(func):
print('正在装饰')
def inner():
print('正在验证权限')
func()
return inner
@wrap
def test():
print('test')
test()
#结果
#正在装饰
#正在验证权限
#test

下面我们来分析一下程序的执行过程
(1)当程序执行test()时,发现函数test()上面有装饰器@wrap,所以会先执行@wrap。@wrap等价于test=wrap(test),可以拆分为两步:
1、执行wrap(test),将函数名test作为参数传递给wrap。在调用wrap函数的过程中,首先会执行print语句,输出“正在装饰”,然后会将形参func指向test()函数体,并将inner()函数的引用返回给wrap(test),作为wrap(test)的返回值。
2、将wrap(test)的返回值赋给test,此时,test只想inner()函数。
到此,我们完成了函数的test()函数。
(2)调用test()指向的函数。因为test指向的是inner()函数,所以此时,调用test()函数相当于调用inner()函数,输出过程如下:
1、输出print语句“正在验证权限”
2、调用func指向的函数。输出“test”。

多个装饰器
多个装饰器可以应用在一个函数上,它们的调用顺序是自上而下的。

def wrap_one(func):
print('--正在装饰1--')
def inner():
print('--正在验证权限1--')
func()
return inner
def wrap_two(func):
print('--正在装饰2--')
def inner():
print('--正在验证权限2--')
func()
return inner
@wrap_one
@wrap_two
def test():
print('---test---')
test()
#结果
#--正在装饰2--
#--正在装饰1--
#--正在验证权限1--
#--正在验证权限2--
#---test---

装饰器对有参函数进行装饰

def wrap(func):
def inner(a,b):#这个地方加参数
print('开始验证')
func(a,b)#这个地方加参数
return inner
@wrap
def test(a,b):
print('a=%d,b=%d'%(a,b))
test(1,2)
#结果
#开始验证
#a=1,b=2

装饰器对带有返回值的函数进行修饰

def func(function_name):
def func_in():
return function_name()
return func_in
@func
def test():
return 'itheima'
result = test()
print(result)
#结果
#itheima

三:常见Python的内置函数

Python提供了很多能实现各种功能的内置函数。内置函数,就是在Python中被自动加载的函数,任何时候都可以使用。

map函数
map函数会根据提供的函数对指定的序列做映射。
map函数的定义如下:
map(function,itrable,……)
在上述定义中,第一个参数function表示第一个函数名,第二个参数iterable可以是序列、支持迭代的容器或迭代器。当调用map函数时,iterable中的每个元素会调用function函数,所有元素调用funciton函数返回的结果会保存到一个迭代器对象中。
如果希望将迭代器对象转换成列表,则可以通过list函数进行转换。此外,还可以使用for循环直接遍历迭代器对象,从而取出其内部的每个元素。

func = lambda x:x+2
result = map(func,[1,2,3,4,5])
print(list(result))
#结果
#[3, 4, 5, 6, 7]

如果map函数中传入的function函数带有两个参数,那么map函数需要传递两个序列,如下:

result = map(lambda x,y:x+y,[1,2,3],[4,5,6])
print(list(result))
#结果:
#[5, 7, 9]

filter函数
filter函数会对指定序列执行过滤操作
filter函数的定义如下
filter(function,iterable)
在上述定义中,第一参数function可以是函数或者None,第二个参数iterable可以是序列、支持迭代的容器或迭代器。返回值为迭代器对象。其中,function函数只能接收一个参数,而且该函数的返回值为布尔值。

func = lambda x:x%2
result = filter(func,[1,2,3,4,5])
print(list(result))
#结果:
#[1, 3, 5]

reduce函数
reduce函数会对参数迭代器的元素进行积累
reduce函数的定义如下:
functools.reduce(function,iterable[,initializer])
在上述定义中,function是一个带有两个参数的函数;第2个参数iterable是一个迭代器对象;initializer表示固定的初始值。reduce函数会依次从迭代器对象中取出元素,和上一次调用function的结果作为参数再次调用function函数。

from functools import reduce
func = lambda x,y:x+y
result = reduce(func,[1,2,3,4,5])
print(result)
#结果
#15

————————————————
版权声明:本文为CSDN博主「菠萝大师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xhb29/article/details/86543871

打赏
VIP部落之Python分站——Python部落格,Python编程爱好者的天堂。
Python部落格 » Python快速编程入门——第7章 高级函数

常见问题FAQ

发表评论

提供最优质的资源集合

立即查看 了解详情