生成器

生成器

生成器,利用迭代器我们可以在每次迭代获取数据时(通过next()方法)按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代的状态需要我们自己记录,进而才能根据当前的状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行迭代使用,可以采用更简便的方法

生成器(generator),生成器是一种特殊的迭代器,他比迭代器更优雅。

创建一个生成器

  • 生成器表达式
    • 把列表推导式的方括号改成圆括号,就成了生成器表达式。

即:列表[] —> ()

li = [x**2 for x in range(6)]
print(li)

gen = (x**2 for x in range(6))
print(gen)

print("通过next()函数取得下一个值")
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))

#  遍历
print("通过for遍历")
gen = (x**2 for x in range(6))
for i in gen :
    print(i,end=" ")
# [0, 1, 4, 9, 16, 25]
# <generator object <genexpr> at 0x00000203CCED0DB0>
# 通过next()函数取得下一个值
# 0
# 1
# 4
# 9
# 16
# 25
# 通过for遍历
# 0 1 4 9 16 25 # 

生成器函数

在函数中如果出现了yield关键字,那么该函数就不再是一个普通函数而是一个生成器函数,调用该函数,会得到一个生成器对象。

def foo():
    yield 1
    yield 2
    return "Error"
    yield 3
f = foo()
print(next(f)) # 程序会停留在对应yield后的语句
print(next(f))
print(next(f)) # 当程序遇到return,return后的语句不会再执行。因此报错。
# 1
# 2
#  File "C://生成器.py", line 39, in <module>
#   print(next(f)) # 当程序遇到return,return后的语句不会再执行。因此报错。
#StopIteration: Error

next 和 yield 进行匹配。如果遇到return ,return后的语句不会再执行,直接抛出StopIteration,终止迭代。

  • 在一个生成器中,如果return后有返回值,那么这个值就是异常的说明,而不是函数的返回值。

构造一个无穷奇数的生成器

def odd():
    n = 1
    while True :
        yield n
        n += 2

odd_num = odd()
print(odd_num)
count = 0
# for i in odd_num:
#     if count > 5:
#         break
#     print(i)
#     count += 1
#
# print(next(odd_num))
for i in range(0,6):
    print(next(odd_num))

通过类手动编写迭代器,实现类似的效果。

class OddIter:
    def __init__(self):
        self.start = 1
    def __iter__(self):
        return self
    def __next__(self):
        self.start += 2
        return self.start
odd = OddIter()

for i in range(6):
    print(next(odd))
Help on generator object:

odd = class generator(object)
 |  Methods defined here:
 |  
 |  __del__(...)
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  close(...)
 |      close() -> raise GeneratorExit inside generator.
 |  
 |  send(...)
 |      send(arg) -> send 'arg' into generator,
 |      return next yielded value or raise StopIteration.
 |  
 |  throw(...)
 |      throw(typ[,val[,tb]]) -> raise exception in generator,
 |      return next yielded value or raise StopIteration.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  gi_code
 |  
 |  gi_frame
 |  
 |  gi_running
 |  
 |  gi_yieldfrom
 |      object being iterated by yield from, or None

None

  • close()
def gen():
    yield 1
    yield 2
    yield 3
    yield 4

g = gen()
print(next(g))
print(next(g))
g.close()
print(next(g)) # 回溯
  • send()
    • x = yield y 语句的含义: send()的作用就是使x赋值为其所传送的值(send的参数),然后让生成器执行到下一个yield。
    • 如果生成器未启动,则必须在使用send()前启动生成器,启动的方法:gen.next()或gen.send(None)执行到第一个yield处。之后就可以使用send(para)不断的传入值。
    • 如果是已启动,则send(para)的作用就是给x赋值为发送的值(send的参数),然后让生成器执行到下一个yield。
def gen():
    value = 0
    while True:
        receive = yield value
        if receive == "e":
            break
        value = "got: %s "% receive

g = gen()
print(g.send(None))
print(g.send("aaa"))
print(g.send(123))
# 0
# got: aaa 
# got: 123 
print(g.send("e")) #  结束 
# Traceback (most recent call last):
# 0
#  File "C:/Users/ou/PycharmProjects/untitled/day01/0730/生成器.py", line 95, # in <module>
#    print(g.send("e"))
# StopIteration
# got: aaa 
# got: 123 

def gen():
    i = 0
    while i < 5:
        temp = yield  i
        print(temp)
        i += 1
obj = gen()
print(next(obj))  # 返回yield后的值,停止!
print(next(obj))
print(obj.send("city")) # 从上次停止处开始, 即给temp赋值,如不赋值,但发生器已启动默认为None
# 0
# None
# 1
# city
# 2
 
  • throw()
    • 手动抛出异常:在生成器暂停的地方抛出类型为 type 的异常,并返回下一个 yield 的返回值。
def gen():
    i = 0
    while i < 5:
        temp = yield  i
        i += 1
        print(temp)

obj = gen()
print(next(obj)) # 0
print(next(obj)) # 1
print(next(obj))# 2
print(obj.throw(Exception, "Method throw called!"))
#  Traceback (most recent call last):
# 0
#   File "C://生成器.py", line 110, in <module>
# None
#     print(obj.throw(Exception, "Method throw called!"))
# 1
#   File "C://生成器.py", line 102, in gen
# None
#     temp = yield  i
# 2
# Exception: Method throw called!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值