1小时前来源:开发者头条
Python generator的基本能力如何?以generator方式实现了一个斐波那契数列生成函数,
def fib(n): if n <= 0: raise StopIteration i = 0 a = 1 b = 1 while i < n: if i < 2: yield 1 else: v = a + b yield v a = b b = v i += 1 # for .. in方式调用 >>> for x in fib(5): print x ... 1 1 2 3 5 # next方式单步调用 >>> x = fib(5) >>> print x.next 1 >>> print x.next 1 >>> print x.next 2 >>> print x.next 3 >>> print x.next 5
从上述代码中可以看到generator的语法规则,通过yield返回数据,外层代码通过next调用触发执行yield之后的代码逻辑。当不存在可执行逻辑时会抛出StopIteration异常。在yield、next、StopIteration之外,还有send函数,
def foo(n): x = 0 for i in xrange(n): x = yield x >>> x = foo(10) >>> x.next 0 >>> x.send(3) 3 >>> x.send(5) 5
send函数可以向generator发送数据,作为yield语句的返回值。
从这两个例子中可以看到generator帮助进行了状态维护,以此让连续代码片段分段执行的能力。在实际中如何应用generator的特性?当然有不少开源项目充分利用了generator,但在具体实际开发中有哪些部分可以直接利用generator而无需引入外界框架呢?
目前遇到的可能合适场景有,
资源的分块缓存加载在加载完部分资源之后调用yield,等待外界调用next再次加载。通过generator维护加载完成状态。
异步代码同步化实现# 异步callback执行方式 def foo: ... do_something_a(lambda data: complete_do_something_a(data)) def complete_do_something_a(data): ... do_something_b(lambda data: complete_do_something_b(data)) def complete_do_something_b(data): ... # generator方式执行 def foo: data = yield do_something_a yield do_something_b(data)
以generator方式来组织代码还需要外层实现一套简单的调度代码,可以根据具体实现复杂情况来考虑是否选择。