【笔记】2022.4.26迭代器、生成器和装饰器

本文详细介绍了Python中的迭代器、生成器和装饰器。迭代器是容器,不能直接创建,只能从序列转换而来,特点是无法获取元素个数且元素一次性获取即消失。生成器是保存生成数据算法的容器,使用yield关键字创建,可以控制产生数据的个数和值。装饰器则是用于给函数添加功能的工具,可以无参或有参,常用于性能统计、日志记录等场景。

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

1. 迭代器


1.1 什么是迭代器

(1)迭代器是容器;程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器

(2)特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;获取元素的时候每次只能获取最前面的那个元素,而且元素取一个就少一个

RIGHT Example:

i1 = iter('abc123')
print(i1) 					# <str_iterator object at 0x00000020195E4580>

i2 = iter([10, 23, 45])
print(i2)					# <list_iterator object at 0x00000020195E4B50>

i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(i3)					# <dict_keyiterator object at 0x0000002019624180>

WRONG Example:

i1 = iter('abc123')
print(len(i1))     # 报错,TypeError: object of type 'str_iterator' has no len()

1.2 查:获取元素

迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失


1.2.1 查单个

next(迭代器):获取迭代器中最前面的那个元素

RIGHT Example:

i1 = iter('abc123')
print(next(i1))             # 'a'
print(next(i1))             # 'b'

i2 = iter([10, 23, 45])
print(next(i2))             # 10
print(next(i2))             # 23
print(next(i2))             # 45
# print(next(i2))           # 报错,StopIteration

print(list(i1))             # ['c', '1', '2', '3']
print(list(i2))             # []

i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(list(i3))             # ['a', 'b', 'c']
# print(next(i3))           # 报错,StopIteration,因为上一步类型转换把i3取完了

1.2.2 遍历

RIGHT Example:

i4 = iter('hello')
for x in i4:
    print('x:', x)

# print(next(i4))     		# 报错,StopIteration

2. 生成器


2.1 什么是生成器

生成器也是容器;其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法

生成器获取数据的方式和特点和迭代器一样


2.2 创建生成器

调用一个带有yield关键字的函数就可以得到一个生成器对象

RIGHT Example:

def func1():
    print('+++')
    print('===')
    yield
    return 100


result = func1()
print('result:', result)
# result: <generator object func1 at 0x0000004EC8F76B30>

2.3 控制生成器产生数据的个数和值

一个生成器产生的数据的个数和值由创建生成器调用的那个函数的函数体在执行时会遇到几次yield以及每次yield后面的值来决定

个数:由遇到的yield的次数决定

值:由yield后面的数据决定

RIGHT Example 1:

def create1():
    yield 100
    yield 200
    yield 300


gen2 = create1()
# print(list(gen2))					# [100, 200, 300]

print(next(gen2))               	# 100
print(next(gen2))               	# 200
print(next(gen2))               	# 300
print(next(gen2))               	# 报错,StopIteration

RIGHT Example 2 永动机:

def create2():
    x = 0
    while True:
        yield x
        x += 1


gen3 = create2()
for x in range(100):
    print(next(gen3))

APPLICATION 写一个生成器,可以创建某个python班级的学生的学号,学号的范围是python0001~python1000:

def student_num(subject):
    for x in range(1, 1001):
        yield f'{subject}{x:0>4}'


python_num = student_num('python')
java_num = student_num('java')
print(next(python_num))						# python0001
print(next(python_num))						# python0002
print(next(java_num))						# java0001
print(next(java_num))						# java0002

# 注意:不能print(next(student_num))

2.4 生成器创建数据的原理

每次获取生成器的数据的时候,就会去执行创建这个生成器的函数体,但是每次执行都只会执行到yield就停下来

RIGHT Example :

def func2():
    print('=======')
    yield 100
    print('+++++++')
    yield 200
    print('!!!!!!!')
    yield 300


gen4 = func2()
print('1.:', next(gen4))
print('2.:', next(gen4))
print('3.:', next(gen4))
"""
=======
1.: 100
+++++++
2.: 200
!!!!!!!
3.: 300
"""

3. 装饰器


3.1 什么是装饰器

给已经定义好的函数添加功能的工具

装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数


3.2 给函数添加功能

RIGHT Example 给函数添加功能,统计函数的执行时间:

# 解决方案1:直接修改原函数
def hello():
    start = time.time()
    print('hello world!')
    end = time.time()
    print(f'总时间:{end - start}')
    
# 解决方案2:写一个新函数
def hello():
    print('hello world!')
    

def total_time(fn, *args, **kwargs):
    start = time.time()
    fn(*args, **kwargs)
    end = time.time()
    print(f'总时间:{end - start}')


total_time(hello)

# 解决方案3:装饰器
def total_time(fn):
    def new_fn(*args, **kwargs):
        start = time.time()
        result = fn(*args, **kwargs)
        end = time.time()
        print(f'总时间:{end - start}')
        return result
    return new_fn

@total_time
def hello():
    print('hello world!')

3.3 无参装饰器

语法:
def 装饰器名(原函数):
    def 添加完功能的新函数(*args, **kwargs):
        调用原函数
        添加新功能
    return 添加完功能的新函数


语法细化:
def 装饰器名(f):
    def new_f(*args, **kwargs):
        result = f(*args, **kwargs)
        新增功能
        return result
    return new_f
        
装饰器名:根据新增的功能来命名

APPLICATION 写一个装饰器在函数调用结束的时候打印’= = = = = = end = = = = = =':

def end_line(f):
    def new_f(*args, **kwargs):
        result = f(*args, **kwargs)
        print('======end======')
        return result

    return new_f


@end_line
def hello():
    print('hello world!')


@end_line
def sum2(num1, num2):
    return num1 + num2


hello()
print(f'和:{sum2(10, 89)}')

APPLICATION 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍:

def multiple(f):
    def new_f(*args, **kwargs):
        result = f(*args, **kwargs)
        if type(result) in (int, float):
            return result * 100
        return result

    return new_f


@multiple
def hello():
    print('hello world!')


@multiple
def sum2(num1, num2):
    return num1 + num2


hello()
print(f'和:{sum2(10, 89)}')

3.4 有参装饰器

有参装饰器语法细化:
def 装饰器名称(参数列表):
    def 无参装饰器(f):
        def new_f(*args, **kwargs):
            result = f(*args, **kwargs)
            新增功能
            return result
        return new_f
    return 无参装饰器

参数列表:看实现装饰器新增功能需不需要额外的数据需要几个

APPLICATION 1 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍数:

def multiple(n):
    def temp(f):
        def new_f(*args, **kwargs):
            result = f(*args, **kwargs)
            if type(result) in (int, float):
                return result * n
            return result
        return new_f
    return temp


@multiple(1000)
def sum2(num1, num2):
    return num1 + num2

print(sum2(10, 20))

APPLICATION 2 写一个装饰器,用法如下:

# 没有装饰器返回值如果是:100  @tag(p) -> <p>100</p>
# 没有装饰器返回值如果是:'abc'  @tag(a) -> <a>abc</a>

def tag(str1):
    def temp(f):
        def new_f(*args, **kwargs):
            result = f(*args, **kwargs)
            return f'<{str1}>{result}</{str1}>'
        return new_f
    return temp


@tag('b')
def sum2(num1, num2):
    num1 + num2
print(sum2(10, 20))

APPLICATION 3 写一个装饰器,用法如下:

# 12 -> @operation('+', 100) -> 112
# 12 -> @operation('-', 20) -> -8
# 12 -> @operation('*', 3) -> 36

def operation(sign, num):
    def temp(f):
        def new_f(*args, **kwargs):
            result = f(*args, **kwargs)
            if type(result) in (int, float):
                return eval(sign.join([str(result), str(num)]))
            return result

        return new_f

    return temp


@operation('+', 100)
def sum2(num1, num2):
    return num1 + num2


print(sum2(10, 20))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sprite.Nym

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

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

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

打赏作者

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

抵扣说明:

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

余额充值