迭代器、生成器和装饰器

总结

  • 迭代器 - iter
"""
迭代器是容器型数据类型(序列),迭代器无法直接获取所有元素,也不能统计元素个数
获取迭代器中的元素的时候,会导致这个元素从迭代器中消失(元素取一个就少一个)
"""
  • 创建迭代器
# 创建迭代器只有两种方式:1)将其他序列转换成迭代器   2)创建生成器
iter1 = iter('abc')
print(iter1)  # <str_iterator object at 0x000001EC36314520>
iter2 = iter([1, 2, 3, 5])
print(iter2)  # <list_iterator object at 0x000001EC36354B50>
iter3 = iter([{'a': 10}, {'b': 20}])
print(iter3)  # <list_iterator object at 0x000001EC36354AF0>
  • 获取迭代器中的元素
# 1)获取单个元素: next(迭代器)
print(next(iter1))  # a
print(next(iter1))  # b
print(next(iter1))  # c
# print(next(iter1))  # 报错 StopIteration  企图获取一个空的迭代器里的元素(停止迭代)

print(next(iter3))  # {'a': 10}
print(next(iter3))  # {'b': 20}

# 2)遍历
for x in iter2:
    print(f'x:{x}')

# x:1
# x:2
# x:3
# x:5
  • 生成器
"""
生成器从获取数据和保存特点来看,就是迭代器的特点。
生成器保存数据的本质,不是保存数据本身,而是保存产生数据的算法
"""
  • 创建生成器 - generator
"""
调用带有yield关键字的函数就可以得到一个生成器
调用带有yield关键字的函数的时候不会执行函数体,也不会获取函数的返回值,只是单纯的创建一个生成器
(函数中yield放在哪儿没有关系)
"""
def func1():
    yield
    print('+++++++')
    return 100


result = func1()
print(result)   # <generator object func1 at 0x00000248DE91D3C0>
  • 确定生成器的元素 - 生成器可以创造的数据
"""
一个生成能产生多少个数据,就看这个生成器对应的函数,执行完函数会遇到几次yield
每次遇到yield的时候,yield后面的数据就是产生的数据
"""
def func2():
    yield 100
    yield 200
    yield 300


result = func2()
print(next(result))  # 100
print(next(result))  # 200
print(next(result))  # 300
# print(next(result))  # StopIteration  报错
  • 生成器产生数据的原理
"""
当通过生成器对象获取元素(不管以什么样的方式获取)的时候,系统会自动执行生成器对应的函数,
执行函数的时候不会直接将整个函数执行完,
而是每次在执行到yield 的时候就会停下来,并且将yield 后面的数据作为结果返回
下次再获取元素的时候从上次结束的位置开始执行
"""
def func3():
    print('1111111111')
    yield 100
    print('2222222222')
    yield 200
    print('333333333')
    yield 300
    print('444444444')


result = func3()
print(next(result))  # 111111111  100
print('!!!!!!!!!!')
print(next(result))  # 222222222  200

# ================================================
def func5():
    yield 10
    yield 20
    yield 30
    yield 40


print(next(func5()))  # 10
print(next(func5()))  # 10

result = func5()
print(next(result))  # 10
print(next(result))  # 20
# 练习:写一个创建学生学号的 生成器:
# 前缀是python,后面试指定范围的值
def func6(subject='python', start=26, end=56):
    for x in range(start, end+1):
        new_str1 = f'{subject}{str(x).zfill(4)}'
        yield new_str1


# result = func6()
# print(next(result))
# print(next(result))
# for _ in range(3):
#     print(next(result))

java = func6('java', 1, 50)
H5 = func6('H5', 1, 50)
for _ in range(5):
    print(next(H5))
    print(next(java))


a = (x for x in range(10))
print(a)
  • 装饰器
"""
装饰器 = 实参高阶函数 + 返回值高阶函数 + 糖语法  (装饰器的本质是函数)
作用:给已经定义好的函数添加功能
"""
def func1():
    start = time.time()
    print('hello world')
    end = time.time()
    print(f'函数执行时间:{end - start}')


func1()


def func2(a, b):
    start = time.time()
    print(a + b)
    end = time.time()
    print(f'函数执行时间:{end - start}')


func2(10, 39)
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 func1():
    print('hello world')


func1()


@total_time
def func2(a, b):
    print(a + b)


func2(100, 232)
  • 无参装饰器的实现方法
"""
装饰器的工作原理:将需要添加功能的函数传给装饰器,装饰器创建一个保留原函数功能,并且添加新功能的一个新的函数,
将添加新功能的一个新的函数,将添加完功能的新函数返回,最后用新的函数替换原来的函数。
*args, **kwargs - 目的是为了给所有的函数都可以添加功能(任意个参数)

装饰器的套路:
def 函数名1(参数1:function):
	def 函数名2(*args, **kwargs)
		添加新功能
		result = 参数1(*args, **kwargs)
		return result
	return 函数2
"""
"""
函数名1  -  装饰器功能对应的名字    
参数1   -   类型是function,指向需要添加功能的原函数,习惯命名成:fn
函数名2  -  添加完功能的新函数, 习惯命名成: new_fn


def 装饰器名称(fn):
    def new_fn(*args, **kwargs):
        新功能
        result = fn(*args, **kwargs)  # 调用原函数的步骤
        return result
    return new_fn
"""
# 写一个装饰器,在函数调用结束的时候打印'end'
def print_end(fn):
    def new_fn(*args, **kwargs):
        result = fn(*args, **kwargs)
        print('end')
        return result
    return new_fn


# 写一个装饰器,将原函数的返回值加100
def add_100(fn):
    def new_fn(*args, **kwargs):
        result = fn(*args, **kwargs)
        if type(result) in (int, float):
            return result + 100
        return result
    return new_fn


@add_100
def func3(nums: int):
    sum1 = 1
    for x in range(1, nums + 1):
        sum1 *= x
    return sum1


print(func3(4))


@add_100
def func4():
    print('你好')


print(func4())
# 练习,写一个装饰器,将函数的返回值变成字符串:
def change_value_type(fn):
    def new_fn(*args, **kwargs):
        result = fn(*args, **kwargs)
        return str(result)
    return new_fn


@change_value_type
def func6():
    return 100


print(func6())  # 100
print(type(func6()))  # <class 'str'>
  • 递归
# 1.递归函数
# 在定义函数的时候调用函数本身,这种函数就是递归函数
# 理论上,循环能做的事情,递归都能做。(能循环实现的时候就不要用递归)
# 注意,使用递归解决循环问题的时候,内存和cpu的消耗,会随着循环次数的增加而不断的增加

def fn():
    print('hello')
    fn()


"""
fn() -> print('hello), fn()
-> print('hello), fn()
-> print('hello), fn()...  死循环
"""
# 2.递归的套路
"""
第一步:找临界值(相当于循环结束的条件), 在临界值的位置结束函数
第二步:找关系,找上一次循环结束的结果和当次循环结束的结果的关系 f(n) 和 f(n-1) 的关系
第三步:假设函数功能已经实现,通过关系用f(n-1)实现f(n)的功能
"""


# 1.计算1+2+3+...+n
def sum1(n):
    # 临界值
    if n == 1:
        return 1

    # 找关系 sum1(n)  和 sum(n-1)
    # sum1(n) = 1+2+3+...n-1+n
    # sum1(n-1) = 1+2+3+...n-1
    # sum1(n) = sum1(n-1) + n
    return sum1(n-1) + n


print(sum1(100))

# 循环方法
def sum2(n):
    sum1 = 0
    for x in range(1, n+1):
        sum1 += x

    return sum1


print(sum2(100))
# 斐波那契数列
def num(n):
    if n == 1 or n == 2:
        return 1
    return num(n-1) + num(n-2)


print(num(10))


# 2.打印下面的图形
"""
n=3
*
**
***

n=4
*
**
***
****
"""


def star(n):
    if n == 1:
        print('*')
        return
    star(n-1)
    print('*' * n)


star(10)

作业

  1. 为函数写一个装饰器,在函数执行之后输出 after
def print_after(func):
    def new_func(*args, **kwargs):
        result = func(*args, **kwargs)
        print('after')
        return result
    return new_func


@print_after
def func1():
    print('hello')


func1()
  1. 为函数写一个装饰器,把函数的返回值乘2再返回在
def new_ele(func):
    def new_func(*args, **kwargs):
        result = func(*args, **kwargs)
        if type(result) in (int, float):
            return result * 2
        return result
    return new_func


@new_ele
def func2(ele):
    return ele


print(func2(10))
  1. 写一个装饰器@tag满足一下功能
def tag(func):
    def new_func(*args, **kwargs):
        result = func(*args, **kwargs)
        return f'<p>{result}</p>'
    return new_func


@tag
def render(text):
    return text


@tag
def render2():
    return 'abc'


print(render('Hello'))  # <p>Hello</p>
print(render2())  # <p>abc</p>
  1. 写一个创建一副扑克的生成器

  1. 使用递归函数画出一下图形
# n = 5
# *****
# ****
# ***
# **
# *
# n = 4
# ****
# ***
# **
# *

def star(n):
    if n == 0:
        return ''
    else:
        return ("*" * n + '\n') + star(n - 1)


print(star(5))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值