Python语言-生成器
生成器
列表生成式
a =
x for x in range(10)
调用type函数来获取变量a的类型。
print(a)
运行结果:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
再来一个例子:
a =
x*2 for x in range(10)
先执行x在范围从0到9的取值这个动作, 然后针对每个取值依次计算它乘以2的结果, 最后把这些结果组合在一起形成一个列表。
print(a)
运行结果:
0, 2, 4, 6, 8, 10, 12, 14, 16, 18
生成器
咱们利用列表生成式能够直接去创建一个列表。可是, 因为会受到那个内存的限制因素所影响, 所以列表的容量肯定它就是处于一个有限的状态里面。
要是说这个列表当中的那些元素, 它可以根据某种特定的算法进行推算的话, 那就采取那种用到再去给它创建的方式。在语言当中这种现象是被称之为生成器的。这就好比是厨师, 他都是那个需要的时候才会去把菜给做出来的。
第一个进行创建生成器方法的操作如下。
这里先给出一个从0到3的范围对象。接着, 把这个范围对象传给生成器表达式来创建a变量。
使用函数把变量a传进去, 然后就可以打印出变量a的类型信息。
请输出 a 通过调用其括号内的空参数形式所得到的结果, 也就是说要执行 a() 这个操作来拿到生成器里面的第一个元素, 这里需要提醒的是, 关于所谓的大叫号这个方法, 也就是 方法, 在目前的情况下是不提倡大家去使用的。
执行打印这个操作, 也就是获取生成器对象的下一个值, 这步动作在逻辑上是和调用 a.() 这个方法的效果等价的, 不过如果你使用的是 2.x 版本的程序环境的话, 那就应该改用 a.next() 这个方法来完成任务。
print(next(a))
print(next(a))
print(next(a)) # 当生成器的值取完后,会报 错误
运行结果:
at 0x000002249CCA1200>
接下来是第二种创建生成器的方法。
def foo():
print('ok')
执行 yield 命令, 返回数值 1。
a = foo()
用print这样的函数去处理变量a, 然后把它显示出来, 这也就是为了看清楚它到底是什么类型。
b 被赋值为下一次调用 a 时返回的值, 也就是说, 在运行 next(a) 这个过程里, 程序已经把 print('ok') 这行代码给执行了。
print(b)
运行结果:
ok
使用 for 迭代生成器
需要补充说明的一点是, 可迭代对象指的是那些内部拥有这个方法的具体对象, 像大家平时会用的列表、还有元组以及字典等, 都属于这样的类型。
这里先给出一个从0到3的范围对象。接着, 把这个范围对象传给生成器表达式来创建a变量。
for i in a:
print(i)
运行结果:
斐波拉契数列
定义一个函数叫做fib, 这个函数接收一个叫max的参数。
n, , after = 0, 0, 1
当n小于max的时候。
yield after # 返回一个 after 值
这里的处理逻辑是, 优先计算出右边的表达式的整体结果, 然后将该结果赋予 left。
在第一次开始循环的这个环节之中, 也就是after等于1, 还有1这种情况发生的时刻。
n += 1
把函数 fib 调用并且传入参数 5, 然后把得到的结果赋值给变量 res, 这个操作的作用就是生成一个生成器。
print(next(res))
print(next(res))
print(next(res))
print(next(res))
print(next(res))
运行结果:
使用 send 方法的时候, 把参数传过去。
def bar():
print('ok1')
首先返回数字1, 然后在后续通过send方法接收数值8, 并将该数值赋值给与变量count相关的位置。
print(count)
print('ok2')
yield 2
b = bar()
send(None)这个方法, 它的作用实际上跟next()这个函数是一样的。不过这里有个注意点, 就是在第一次调用send方法之前, 如果之前没有先执行过一次next调用, 那么就只能用send(None)这种做法来处理。
执行 next 方法调用对象 b, 并将得到的结果进行打印输出, 这个被输出的数值 1, 其实就是从函数里面通过 yield 关键字返回回来的那个值。
b.执行发送操作, 也就是调用那个叫send的方法来传递数值8, 这个动作使得程序流程跳转并暂停在标记为的那个位置, 在这一瞬间系统会将接收到的数字8指派给名为count的那个变量。
运行结果:
ok1
ok2
希望这篇文章能够给你带来一些帮助, 总而言之, 各位同学要记住相关的关于技术方面的消息和情报信息都会是在职坐标这个上面可以找到。