Python_装饰器,迭代器,生成器

本文深入探讨Python中的装饰器和迭代器的概念,解释了装饰器如何在不修改原函数结构的情况下增强其功能,以及迭代器如何实现对数据集的高效遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

●装饰器


装饰器用来增强 函数 的功能 但是不改变其原有的结构与功能 。 在代码运行期间 动态的添加功能 称为 装饰器。

如何理解装饰器?

1.不改变函数结构,即不对函数本身结构体做任何修改;
2.增强函数功能;比如起跳时能带一道彩虹,那么能构造彩虹功能即可以定义为起跳函数的装饰器,并不影响起跳这个函数;
3.本质上,装饰器就是一个返回函数的高阶函数。

下面我们定义一个起跳函数

def jump():
    print('我正在蹦跶')

定义一个装饰器

def rainbow(main):
    def make_rainbow(*args,**kwargs):
        print('你被挂上了彩虹:%s'%(main.__name__))
        return main(*args,**kwargs)
    return make_rainbow 

看这个装饰器(decorator),因为rainbow是一个装饰器 ,所以他是接受一个函数作为参数(main)的。
借助Python的@语法,把decorator置于函数的定义处:

@rainbow
def jump():
    print('我正在蹦跶')

执行jump:

if __name__ == '__main__':
    jump()

这里写图片描述
我们从结果上来看,是先执行 装饰器 然后用才执行主函数 那么具体步骤是怎样的呢?

把@raninbow放到jump()函数的定义处,相当于执行了语句:jump=raninbow(jump);
那么 raninbow 返回的是一个新函数 jump() ,那么现在同名的now变量指向了新的函数 ,在rainbow()函数内,首先打印日志,再紧接着调用原始函数 。

import json
'''
装饰器
'''
def guess_with(func):
    def rooftop_status():
        result = func()
        print("天台见")
        return result
    return rooftop_status

@guess_with
def german_team():
    print("德国必胜")

# german_team()
'''函数名可以赋值给变量'''
def a(name):
    print("我是{}!慌得一批!".format(name))
a("梅西")
y = a
y("乐福")

'''高阶函数
    高阶函数满足其一即为高阶函数:
    a.可以接受函数名作为实参;
    b.返回值中可以包含函数名
    '''
r = map(lambda x:x*3, [3,3,4,5,6])
for i in r:
    print("当前天台人数:", i)

# 定义一个可以返回函数的函数 也就是高阶函数
def f(l):
    return map(lambda x: x*10,l)
aaa = f([10,22,333])
for i in aaa:
    print("已跳天台人数:", i)

'''有了以上的两个概念 实现一个类似的装饰器'''

def status(func):  #接受一个 函数名参数 并返回了该函数名 并不会修改原函数 只是增加了一个本身带有的表动
    print('慌得一批!')
    return func
def name():
    print("我是勒布朗")

'''在调用时 这里有个缺陷 就是函数调用方式改变了;即不是原本的name,而是 t 
    那么改成 name = status(name) 不就可以了?但是每次使用这样的装饰器 都要写这一句
    那么简化一下 python提供了一个语法糖 @  在每个被装饰的函数上使用这个@即为代替name=status(name)
'''
name = status(name) #
name()

def status(func):
    print('慌得一批')
    return func

@status
def name():
    print('LBJ')

name()
"""
    装饰器的工作原理:
    ①构建一个高阶函数 参数为函数 返回的也是函数
    ②再利用语法糖@ 简化赋值操作
"""
def guess_win(func):
    def rooftop_status():
        result = func()
        print('天台已满,请排队')
        return result
    return rooftop_status
@guess_win
def german_team():
    print('德国必胜')
    return '赢了会所嫩模!输了下海干活!'
x = german_team()
print(x)
"""
    装饰器本事就是函数,其参数是另一个函数(被装饰的函数)
    装饰器通常会额外处理被装饰的函数,然后把它返回,或者将替换成另外一个函数或可调用对象
"""

●迭代器


迭代器 :可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。实现 迭代迭代器协议的 容器对象
注:
访问者无需关注迭代器内部 仅需要通过 next() 方法 去取下一个内容
不能随机访问 集合中的某个值 只能从头到尾访问
访问到一半时 不能往回退
便于循环较大的数据集合 节省内存

a  = iter([1,2,3,4,5,555,666])
>>> a = iter([1,2,3,4,56,77])
>>> a.__next__()
1
>>> a.__next__()
2
>>> a.__next__()
3
>>> a.__next__()
4
>>> a.__next__()
56
>>> a.__next__()
77

●生成器


生成器 :一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);
如果函数中包含yield语法,那这个函数就会变成生成器。

>>> def odd():
...     print 'step 1'
...     yield 1
...     print 'step 2'
...     yield 3
...     print 'step 3'
...     yield 5
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
判断一个函数是否是一个特殊的 generator 函数?可以利用 isgeneratorfunction 判断:
下面使用 yield 书写一个斐波那契 函数:

#1.常规版本
def fab(max):
    n,a,b = 0,0,1
    while n <max:
        print(b)
        a,b,=b,a+b
        n =n+1
>>> from inspect import isgeneratorfunction 
>>> isgeneratorfunction(fab) 
False
#2.yield版本
def fab(max):
    n,a,b = 0,0,1
    while n <max:
        yield b
        a,b,=b,a+b
        n =n+1
>>> isgeneratorfunction(fab) 
False

yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰;
如:
这里写图片描述
参考自:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值