第7章 高级函数

一、闭包

如果一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数就会被称为闭包。闭包必须满足如下三个条件:
(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

二:装饰器

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

  1. 什么是装饰器
    装饰器本质是一个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”。

  1. 多个装饰器
    多个装饰器可以应用在一个函数上,它们的调用顺序是自上而下的。
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---
  1. 装饰器对有参函数进行装饰
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
  1. 装饰器对带有返回值的函数进行修饰
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中被自动加载的函数,任何时候都可以使用。

  1. 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]
  1. 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]
  1. 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值