在Python中聚合和延迟函数执行

在Python中聚合和延迟函数执行,python,Python,我在python中有自己的函数,偶尔会被其他代码每秒多次调用。我的函数如下所示: def doIt(id): doSomething(id) 因此,doSomething()的调用次数与doIt()的调用次数相同,这会造成麻烦。如何在最后一次调用doIt(id)5秒后聚合doIt(id)调用和doSomething(id)调用一次?id参数是可变的,调用doIt(123)应该对doIt(789)没有影响。如果我读对了,你的问题是有人可以在五秒钟内多次调用doIt(10),但你只希望每五

我在python中有自己的函数,偶尔会被其他代码每秒多次调用。我的函数如下所示:

def doIt(id):
    doSomething(id)

因此,doSomething()的调用次数与doIt()的调用次数相同,这会造成麻烦。如何在最后一次调用doIt(id)5秒后聚合doIt(id)调用和doSomething(id)调用一次?id参数是可变的,调用doIt(123)应该对doIt(789)没有影响。如果我读对了,你的问题是有人可以在五秒钟内多次调用doIt(10),但你只希望每五秒钟调用一次
doSomething(10)

在这种情况下,您可以相对轻松地在没有线程的情况下执行此操作
doIt()
可以记住上次使用某些参数调用
doSomething()
的时间,并且只有在不是特别新的时候才能再次调用它

import timeit

doSomething_calls = {}

def doIt(id):
    now = timeit.default_timer()  # wallclock time in seconds
    if id in doSomething_calls:
        if now - doSomething_calls[id] > 5:  # If the last real call was more than 5 seconds ago
            doSomething(id)  # Do a new call
            doSomething_calls[id] = now  # And update the time we last did a real call
    else:
        doSomething(id)
        doSomething_calls[id] = now
明智地使用
{}.get()
,可以显著减少该函数,但我将把它作为练习留给您。如果没有人一下子把所有的东西都扔给你,学习已经够难的了。:)

或者,如果您希望对
doSomething(x)
的调用等待5秒钟,直到没有任何对
doIt(x)
的调用,则需要线程或子进程来避免程序在等待时锁定。以下是您如何做到这一点:

import threading
import time
import timeit

doIt_calls = {}

def doIt(id):
    doIt_calls[id] = timeit.default_timer()

def doSomethingThread():
    to_delete = []
    while alive:
        now = timeit.default_timer()
        for id, wallclock_time in doIt_calls.items():
            if now - wallclock_time > 5:  # If the last time `doIt(id)` was called was longer than 5s ago
                doSomething(id)  # Enact the `doSomething()` call
                to_delete.append(id)  # Remove the scheduled call from the dictionary so we don't immediately call it again next loop.
        for id in to_delete:
            del doIt_calls[id]
        time.sleep(0.1)

alive = True  # set this False after the end of your program to kill the thread

thread = threading.Thread(target=doSomethingThread)
thread.start()

# Rest of your program

alive = False  # Tell the thread to die after it's done with the current loop

听起来您需要一个线程和/或time.sleep此解决方案只有在永远调用doIt(id)时才有效。不幸的是,它被称为apx。20倍,只需2秒,在不久的将来,它将不再被调用。这就是为什么我需要doSomething(id)在最后一次调用doIt(id)5秒后只调用一次。我的解决方案最多每5秒调用一次
doSomething()
,这不是你想要的吗?您的意思是在最后一次调用
doIt(x)
5秒后调用
doSomething(x)
?在这种情况下,您将需要线程来避免锁定程序。如果是这种情况,请告诉我,我将编辑我的答案。是的,doSomething(x)应该在最后一次调用doIt(x)后5秒调用,必须更改为循环以在
doIt_calls.items()中迭代
使其正常工作,但无论如何,我得到了RuntimeError:字典在迭代过程中改变了大小。这就是我从内存而不是交互式解释器编写字典的结果。再次编辑我的答案,这应该是最后一次了:D