Python 生成器和减少
Python generators and reduce
我正在开发一个 Python3 tornado
Web 服务器,它使用 @gen.coroutine
装饰器为 GET 请求提供异步协程。我想使用库中的这个函数:
@gen.coroutine
def foo(x):
yield do_something(x)
这很简单:
@gen.coroutine
def get(self):
x = self.some_parameter
yield response(foo(x))
现在假设有多个相同类型的函数foo1
、foo2
等。我想做一些类似 ...foo3(foo2(foo1(x).result()).result())...
和 yield
的事情,而不仅仅是 get
方法中的 response(foo(x))
。
我认为使用 reduce
和 result
方法会很容易。但是,由于 tornado
的工作方式,我无法使用 result
方法将 foo
强制为 return。这意味着 yield reduce(...)
给出了一个错误:"DummyFuture does not support blocking for results"。从 SO 和其他地方的其他答案中,我知道我将不得不使用 IOLoop
或其他我不太理解的东西,并且...
...我的问题是,我怎样才能 避免评估 all foo
s 和 yield
来自 get
方法的未计算块?
Edit:这不是 的副本,因为我想:1. 嵌套很多函数和 2. 尝试 not 立即评估。
在 Tornado 中,您必须 yield
协程中的 Future 才能获得结果。评论 Tornado's coroutine guide.
您可以编写一个作为协程的减速器。它运行每个协程以获得 Future,调用 yield
与 Future 以获得结果,然后在该结果上运行下一个协程:
from tornado.ioloop import IOLoop
from tornado import gen
@gen.coroutine
def f(x):
# Just to prove we're really a coroutine.
yield gen.sleep(1)
return x * 2
@gen.coroutine
def g(x):
return x + 1
@gen.coroutine
def h():
return 10
@gen.coroutine
def coreduce(*funcs):
# Start by calling last function in list.
result = yield funcs[-1]()
# Call remaining functions.
for func in reversed(funcs[:-1]):
result = yield func(result)
return result
# Wrap in lambda to satisfy your requirement, to
# NOT evaluate immediately.
latent_result = lambda: coreduce(f, g, h)
final_result = IOLoop.current().run_sync(latent_result)
print(final_result)
我正在开发一个 Python3 tornado
Web 服务器,它使用 @gen.coroutine
装饰器为 GET 请求提供异步协程。我想使用库中的这个函数:
@gen.coroutine
def foo(x):
yield do_something(x)
这很简单:
@gen.coroutine
def get(self):
x = self.some_parameter
yield response(foo(x))
现在假设有多个相同类型的函数foo1
、foo2
等。我想做一些类似 ...foo3(foo2(foo1(x).result()).result())...
和 yield
的事情,而不仅仅是 get
方法中的 response(foo(x))
。
我认为使用 reduce
和 result
方法会很容易。但是,由于 tornado
的工作方式,我无法使用 result
方法将 foo
强制为 return。这意味着 yield reduce(...)
给出了一个错误:"DummyFuture does not support blocking for results"。从 SO 和其他地方的其他答案中,我知道我将不得不使用 IOLoop
或其他我不太理解的东西,并且...
...我的问题是,我怎样才能 避免评估 all foo
s 和 yield
来自 get
方法的未计算块?
Edit:这不是
在 Tornado 中,您必须 yield
协程中的 Future 才能获得结果。评论 Tornado's coroutine guide.
您可以编写一个作为协程的减速器。它运行每个协程以获得 Future,调用 yield
与 Future 以获得结果,然后在该结果上运行下一个协程:
from tornado.ioloop import IOLoop
from tornado import gen
@gen.coroutine
def f(x):
# Just to prove we're really a coroutine.
yield gen.sleep(1)
return x * 2
@gen.coroutine
def g(x):
return x + 1
@gen.coroutine
def h():
return 10
@gen.coroutine
def coreduce(*funcs):
# Start by calling last function in list.
result = yield funcs[-1]()
# Call remaining functions.
for func in reversed(funcs[:-1]):
result = yield func(result)
return result
# Wrap in lambda to satisfy your requirement, to
# NOT evaluate immediately.
latent_result = lambda: coreduce(f, g, h)
final_result = IOLoop.current().run_sync(latent_result)
print(final_result)