Python基础34:函数的生成器(自定义的迭代器)

# **************************************************************************
# Python学习
# **************************************************************************
# ** 所属主题: 函数
# ** 所属分层: 34 生成器
# ** 功能描述: 34 生成器
# ** 创 建 者: 陈红伟
# ** 创建日期: 2021/4/13 11:47 下午
# **************************************************************************
# ** 修改日期     修改人    修改内容
# ** 2021/4/13   陈红伟    新增学习内容代码
# **************************************************************************

def func():
    return 1
    return 2
    return 3
    return 4

# 上述只能返回一个值1,那如果想返回多次值呢? ====  yield


# 如何得到自定义的迭代器: 生成器 就是 迭代器
# 在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会生产一个生成器对象,生成器即自定义的迭代器


def func():
    print("第1次")
    yield 1
    print("第2次")
    yield 2
    print("第3次")
    yield 3
    print("第4次")


g = func()
print(g)  #  generator:生成器
res = g.__next__() # 第1次
#上行代码 会运行函数体代码,直到遇到yield就停下来
# 想看到此时的返回值
print(res) # 1

res2 = next(g) # 第2次   注意⚠️:g.__next__() 和 next(g)的用法是一样的
print(res2) # 2

res3 = g.__next__() # 第3次
print(res3) # 3

# res4 = g.__next__() # 继续执行程序(所以会打印出" 第4次")并抛出异常如下:
# 第4次
# Traceback (most recent call last):
#   File "/Users/chenhongwei/PycharmProjects/python-learn/Egon202003/01 python基础/34 生成器.py", line 50, in 
#     res4 = g.__next__()
# StopIteration

# 小知识:
# g.__next__() 和 next(g)的用法是一样的
# len('q') 和 'q'.__len__()的用法也是一样的;还有很多函数有类似的用法
print(len('q')) # 1
print('q'.__len__()) # 1




# 应用案例:写一个不占用内存空间的函数,就是模仿写个range()函数
def my_range(start,stop,step=1):
    print('start...')
    while start<stop:
        start+=step
        # return start
        yield start  #不能用return,不然就退出函数了,所以用yield。
    print('end...')

for n in my_range(1,7,2):
    print(n)
# start...
# 3
# 5
# 7
# end...

# 在后面学到【并发编程】的时候可以更深的体现yield作用:运行挂起。
# yield表达式: x = yield 返回值
# 是要有yield该函数就是生成器

def dog(name):
    print(f'{name}准备吃东西')
    while True:
        x = yield None  # x 是拿到yield接收到的值,可以通过send()传入值
        print(f'{name}吃了{x}')


g = dog('xiaolan')
next(g)  # xiaolan准备吃东西
"""
send()可以为yield赋值,并继续运行
"""
g.send('骨头 ') # xiaolan吃了骨头
g.send('') # xiaolan吃了
g.send('小匣子') # xiaolan吃了小匣子
# g.send('1','2') # TypeError: send() takes exactly one argument (2 given) # 只需要一个参数,但你传入了两个值
g.send(['gutou','xiaoyugan']) # xiaolan吃了['gutou', 'xiaoyugan']
"""
还可以关闭,关闭后无法传值
"""
g.close()
# g.send(1) # StopIteration 已关闭,无法再传值


# yiled在程序中的执行情况:
def func():
    list1 = []
    print('start....')
    x = yield list1
    print('proceding.....',x)
    list1.append(x)
    y = yield list1
    print(y)

g = func()
# g.send(1)     # TypeError: can't send non-None value to a just-started generator  必须先初始化,在使用send之前
res = g.__next__()
# start....  运行到115行,然后返回结果给res。此时结果为yield后面定义的返回值,此处即为list1,并且yield是没有执行的,所以yield是None,x也是,没有被赋值的
print(res)
# []   因为此时结果为yield后面定义的返回值,此处即为list1,所以是返回[]
# g.send() # TypeError: send() takes exactly one argument (0 given) send必须要给予参数
res2 = g.send(1111)    # 此时会在上次停在yield的位置继续运行,此时第1个yield的值是1111,并且此时x=1111,此时返回值为:list1.append(x) ,此处即为[1111]。并且第二个yield为None。
# proceding..... 1111
print(res2)
# [1111]
# res = g.send(3333)  # StopIteration 因为后面没有第三个yield了,所以报错

你可能感兴趣的:(Python基础,python,迭代器,生成器)