当前位置: 首页 > 面试题库 >

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

段干子晋
2023-03-14
问题内容

Scipy最小化功能(仅作为示例使用)可以选择在每个步骤中添加一个回调函数。所以我可以做类似的事情,

def my_callback(x):
    print x
scipy.optimize.fmin(func, x0, callback=my_callback)

有没有办法使用回调函数来创建fmin的生成器版本,以便我可以做,

for x in my_fmin(func,x0):
    print x

似乎可以将收益和收益进行某种组合,但我可以想到任何事情。


问题答案:

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

from thread import start_new_thread
from Queue import Queue

def 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_donejoin

    # 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


 类似资料:
  • 问题内容: 我正在编写一个通用函数,该脚本将在脚本的多个位置重用。 该函数使用ajax(使用jQuery库),所以我想以某种方式将一个函数(或代码行)传递给该函数以在ajax完成时执行。我相信这应该是一个回调函数,但是在阅读了一些回调答案之后,我仍然对如何实现这种情况感到困惑。 我当前的功能是: 有了这个功能,我希望能够以与其他jQuery功能相同的方式来做某事,即: 问题答案: 只需为函数提供另

  • 我试图将我的Javascript撰写函数翻译成Python,但我对最后一个有问题。我如何推广未知数量的函数? 读完本文后,我想避免使用方法。 javascript: 蟒蛇: 感谢所有的改进。。。

  • 问题内容: 我想使用Promise,但是我有一个类似以下格式的回调API: 1. DOM加载或其他一次事件: 2.普通回调: 3.节点样式回调(“ nodeback”): 4.带有节点样式回调的整个库: 如何在promise中使用API​​,如何“承诺”它? 问题答案: 承诺有状态,它们从待定状态开始,可以解决: 完成 意味着计算成功完成。 拒绝 表示计算失败。 承诺返回函数 绝不应该抛出,而应该

  • 问题内容: 我正在使用播放框架和Apache Kafka。 我有一个POST方法,它将消息发送到Kafka。Kafka有一个API方法 public java.util.concurrent.Future send(ProducerRecord记录,回调回调) 其中Javadoc说 异步将记录发送到主题,并在确认发送后调用提供的回调。 我正在使用play框架公开此功能。我想从Controller方

  • 我正在使用play框架和Apache Kafka。 我有一个POST方法,它向Kafka发送消息。Kafka有一个API方法 公共java.util.concurrent。未来发送(生产记录记录、回调) 其中Javadoc说 异步发送记录到主题,并在发送被确认时调用提供的回调。 我将使用play框架公开此功能。我想返回一个<代码>promise

  • 问题内容: 我不太了解如何使用jQuery的ajax函数的回调。 我在JavaScript中有以下代码: 在服务器端(AppEngine / Python),我获取了回调参数的值并使用 但是随后我在浏览器控制台中看到了。 处理此问题的正确方法是什么?现在,我得到了所需的结果,但是我知道这不正确的事实困扰着我。 问题答案: 这就是我在我身上所做的