栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

将带有回调的函数转换为Python生成器?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

将带有回调的函数转换为Python生成器?

如注释中所指出的,您可以使用在新线程中进行操作

Queue
。缺点是您仍然需要某种方法来访问最终结果(最后
fmin
返回什么)。下面的示例使用一个可选的回调函数来做一些事情(另一个选择就是也产生它,尽管您的调用代码必须区分迭代结果和最终结果):

from thread import start_new_threadfrom Queue import Queuedef my_fmin(func, x0, end_callback=(lambda x:x), timeout=None):    q = Queue() # fmin produces, the generator consumes    job_done = object() # signals the processing is done    # Producer    def my_callback(x):        q.put(x)    def task():        ret = scipy.optimize.fmin(func,x0,callback=my_callback)        q.put(job_done)        end_callback(ret) # "Returns" the result of the main call    # Starts fmin in a new thread    start_new_thread(task,())    # Consumer    while True:        next_item = q.get(True,timeout) # Blocks until an input is available        if next_item is job_done: break        yield next_item

更新: 要阻止下一次迭代的执行,直到使用者完成对最后一个迭代的处理为止,还必须使用

task_done
join

    # Producer    def my_callback(x):        q.put(x)        q.join() # Blocks until task_done is called    # Consumer    while True:        next_item = q.get(True,timeout) # Blocks until an input is available        if next_item is job_done: break        yield next_item        q.task_done() # Unblocks the producer, so a new iteration can start

请注意,这

maxsize=1
是不必要的,因为直到消耗完最后一个项目,才会有新项目添加到队列中。

更新2:
还请注意,除非最终所有生成器都检索到该生成器,否则创建的线程将死锁(它将永远阻塞并且其资源将永远不会释放)。生产者正在等待队列,并且由于它存储对该队列的引用,因此即使消费者使用,它也不会被gc回收。然后,队列将变得不可访问,因此没有人能够释放该锁。

如果可能的话,一个干净的解决方案还是个未知数(因为它取决于代替的特定功能

fmin
)。可以使用解决方法
timeout
,如果
put
阻塞时间过长,则使生产者引发异常:

    q = Queue(maxsize=1)    # Producer    def my_callback(x):        q.put(x)        q.put("dummy",True,timeout) # Blocks until the first result is retrieved        q.join() # Blocks again until task_done is called    # Consumer    while True:        next_item = q.get(True,timeout) # Blocks until an input is available        q.task_done()        # (one "task_done" per "get")        if next_item is job_done: break        yield next_item        q.get() # Retrieves the "dummy" object (must be after yield)        q.task_done() # Unblocks the producer, so a new iteration can start


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/638461.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号