生成器

一、生成器与yield

若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象。

def my_range(start, stop, step=1):
    print("start...")
    while start < stop:
        yield start
        start+=step
    print("end...")

g=my_range(0,3)
print(g)  # <generator object my_range at 0x00000000024A60C8>

生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器

print(g.__next__)  
# <method-wrapper '__next__' of generator object at 0x00000000022860C8>
print(g.__iter__) 
 # <method-wrapper '__iter__' of generator object at 0x00000000022860C8>

因而可以用next(生成器)出发生成器所对应函数的执行

print(next(g))
# start...
#  0
print(next(g))
# 1
print(next(g))
# 2
print(next(g))
#end...
print(next(g))
Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/Test/180days/函数/test.py", line 213, in <module>
    print(next(g))
StopIteration

既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:

for i in g:
    print(i)
    
start...
0
1
2
end...

有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起来,用来返回多次值。

二、yield表达式应用

在函数内可以采用表达式形式的yield

def eater():
    print("Ready to eat!")
    while True:
        food = yield
        print("get the food %s,ready to eat"%food)
e = eater()   # 得到生成器对象
print(e)   # <generator object eater at 0x0000000001D97B48>
next(e)  # 初始化,让函数挂起在food = yield, 等待调用g.send( )方法为其传值
# Ready to eat!
e.send("鸡腿")
# get the food 鸡腿,ready to eat

针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food = yield的位置,等待g.send()方法为函数体传值,g.send(None)等同于next(g).
可以编写装饰器来完成为所有表达式形式yield对应生成器的初始化操作,如下:

def init(func):
    def wrapper(*args,**kwargs):
        e = func(*args,**kwargs)
        next(e)  # 初始化
        return e
    return wrapper

@init
def eater():
    print("Ready to eat!")
    while True:
        food = yield
        print("get the food %s,ready to eat"%food)

表达式形式的yield也可以用于多次返回值,即 变量名 = yield 值的形式,如下:

def eater():
    print("ready to eat")
    food_list = []
    while True:
        food = yield
        food_list.append(food)
        print(food_list)

e = eater()
next(e)
e.send("蒸羊羔")   # ['蒸羊羔']
e.send("蒸熊掌")   # ['蒸羊羔', '蒸熊掌']
e.send("蒸鹿尾儿")   # ['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']

三、三元表达式、列表生成式、生成器表达式

3.1 三元表达式

三元表达式是python为我们提供的一种简化代码的解决方案,语法如下:
res = 条件成立时返回值 if 条件 else 条件不成立时返回的值
举例如下:

def max(x, y):
    if x > y:
        return x
    elif x < y:
        return y

三元表达式:

x = 0
y = 1
res = x if x>y else y

3.2 列表生长式

列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生长列表。
例子如下:

egg_list = []
for i in range(10):
    egg_list.append("鸡蛋%s"%i)

列表生成式:

egg_list = ["鸡蛋%s"%i for i in range(9)]

3.1 生成器表达式

创建一个生成器对象有两种方式,一种是调用yield关键字的函数,另一种就是生成器表达式,与列表生成式的格式相同,只是把[ ]换成( ) ,即:

(expression for item in iterable if condition)

列表生成器返回值是一个列表
生成器表达式返回的是一个生成器对象,其优点是节省内存(一次只产生一个值在内存中)
如果要读取一个大文件,应该基于生成器表达式的方式完成:

with open("db.txt","rb") as f:
    nums = (len(line) for line in f)
    total_size = sum(nums)  # 依次执行next(nums),然后累加到一起得到结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值