python的匿名函数、迭代器、生成器与装饰器

5.8.匿名函数

5.8.1.当创建函数时有时不需要显示的定义函数,直接省略函数名传入参数计算即可,省略函数的命名,通过水平不发生表达式实现函数

5.8.2.使用lambda关键字创建匿名函数

  • 所谓匿名即不在使用def关键字来创建函数

  • lambda只是一个表达式,不是一个代码块,函数体比def简单

  • lambda仅仅封装有限的逻辑语句

5.8.3.格式:lambda 参数:表达式

lambda x :x*x
#相当于
def fun(x):
    return x*x
  • lambda是匿名关键字

  • lambda之后的x为函数参数,相当于原先的形参

  • x*x为执行代码

5.8.4.匿名函数只能有一个表达式,有自己的命名空间,不用再写return语句,表达式的结果就是其返回值

5.9.迭代器

5.9.1.迭代:通过for循环遍历对象的每一个元素过程

5.9.2.迭代器:是一种可以被遍历的对象,可以作用于next()函数,迭代器对象从第一元素开始向后进行访问,直至最后一个元素,只能向后遍历,不能向前回溯,与列表最大的区别就是列表遍历方向任意

5.9.3.迭代器的常用方法:iter()和next()

list1=[1,2,3,4,5,6,7,8]
lt=iter(list1)  #创建迭代器对象lt
for i in lt:
    print(i,end=' ')

5.9.4.迭代器(iterator)与可迭代(iterable)的区别

  • 凡是可作用于for循环的对象都是可迭代类型

  • 凡是可作用于next()函数的对象都是迭代器类型

  • list、dict、str等都是可迭代的但不是迭代器,应为next()函数无法调用它们

  • for循环本质上是通过调用next()函数实现下一个访问的

5.10.生成器

5.10.1.产生原因:由于序列或集合内的元素个数非常巨大,如果全部生成制造再一次性装入内存会对计算机造成非常大的存储压力,如果元素结果可以按照某些算法可以推算出来,需要计算哪一个就生成哪一个,不必完整的创建元素集合,从而节省大量内存空间。所以在python中一边循环一边计算的机制称为生成器(generator)

5.10.2.在python中使用关键字(yield)可以返回函数。使其变成一个生成器

5.10.3.运行机制:调用函数生成器过程中,每次遇到yield时,函数会暂停执行,并保存当前所用的运行信息,向主调函数出返回结果,并在下一次执行next()方法时从当前位置继续执行

#斐波那契函数
def fib(n):
    a,b,c=0,1,0
    while 1:
        if c >n:
            return
        yield  a
        a,b=b,a+b
        c=c+1
​
f1=fib(10)
for i in f1:
    print(i,end=" ")
print(type(f1))

5.11.装饰器

5.11.1.先从一个函数开始:

def hello():
    print('hello world')
 
​
hello()

5.11.2.上例定义一个hello函数,现在需要增加一个功能:

def hello():
    print('===start===')
    print('hello world')
    print('=== end ===')
​
​
hello()

或者:

#第二种
def hello():
    print('hello world')
​
print('===start===')
hello()
print('=== end ===')

问题:

第一种方法会改变函数的执行代码

第二种如果多次调用,每次都需要增加开始和结束的特效,将会非常消耗机器性能,较为麻烦

则能不能在不改变函数内部功能原始代码和参数及调用方式等信息,又想给该函数增加新功能?

可以使用装饰器,装饰该函数,再不改变原函数的情况下,增加功能

5.11.3.函数的高阶使用

  • 定义一个函数

def add(a,b):
    return a+b
  • 调用:

def add(a,b):
    return a+b
​
print(add(2,3))
  • add函数是有返回值的,若输出add不加括号

def add(a,b):
    return a+b
​
print(add(2,3))
print(add)
print(type(add))
  • 结论:一个函数名加上括号就会被执行,函数也和整数、字符串、浮点数一样都是对象,基于上述理论:

a=print
a('hello world')
#解释:那print赋值给a,a('hello world')等价于print('hello world')

继续改进:

def output():
    return print
​
​
output()('hello world')
#解释:任何返回值都可以在调用时直接替换这个函数
#output()('hello woeld')中output()会被替换为print等价于print('hello world')

继续改进:

def output():
    print('hello world')
def act(func):
    func()
​
act(output)
#解释:定义一个output函数可以输出hello world
#但没有直接调用,而是写了一个act函数,act函数的参数是一个函数名,作用就是调用act函数时会间接调用output()函数从而输出hello world
  • 结论:一个函数名称作为一个函数的参数传递给另一个函数时(实参高阶函数),返回值中包含函数名(返回值高阶函数),这里说的函数名本质为函数首地址,若把函数名当做一个参数传递给另一个函数,然后再另一个函数内部做一些操作,则可以实现不修改源代码的情况下从而变更函数功能

5.11.4.基于上述演变,得出如下示例:

def deco(func):
    def inner():
        print('===start===')
        func()
        print('=== end ===')
​
    return inner
​
​
def hello():
    print('hello world')
​
hello=deco(hello)
hello()
  • 函数deco即hello会被装入内存,等待被执行

  • 执行hello=deco(hello),调用deco函数,将hello函数名作为实参传递过去

  • 执行deco(func)函数,其中func等价于hello函数,inner函数装入内存等待被执行,最后返回inner函数名并到hello=deco(hello)函数调用出,hello会被inner覆盖,此时hello就是inner函数

  • 执行hello()函数,由于hello已被inner覆盖则相当于执行inner()函数

  • 执行inner函数输出修饰语句,输出func()函数结果,由于func指向最早的hello函数则输出hello world

  • 结论:本段代码本质上修改了调用函数,但表面上为修改调用方式,实现了附加功能,通俗一点来说就是把函数当做一个合数,deco是大盒子、inner是中盒子、hello是小盒子,程序中将小盒子hello传递给大盒子deco中的中盒子inner,再把中盒子inner执行一次,这就是装饰器

  • 如果需要多次修改,可以装饰多次

def deco(func):
    def inner():
        print('===start===')
        func()
        print('=== end ===')
​
    return inner
​
​
def hello():
    print('hello world')
​
def nihao ():
    print('你好,世界!')
​
​
def py():
    print('好棒')
​
​
hello=deco(hello)
hello()
​
nihao=deco(nihao)
hello()
​
py=deco(py)
py()

5.11.2.装饰器

  • 器:指的是工具,可以定义成函数

  • 装饰:指定是为其他事物添加额外点缀

  • 装饰器:定义一个函数,该函数是用来为其他函数添加额外功能的

  • 应用场景:应用于切面操作的场景,如:插入日志、性能测试、事物处理、缓存、权限效验等

  • 语法糖:装饰器的语法简化写法,如:

def deco(func):
    def inner():
        print('===start===')
        func()
        print('=== end ===')
​
    return inner
​
@deco    #等价于hello=deco(hello)
def hello():
    print('hello world')
​
​
​
​
hello()
# @deco写在被装饰的def hello()函数之前

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流年ꦿ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值