在循环中仅执行一次函数的高效方法

94 投票
19 回答
191978 浏览
提问于 2025-04-16 06:36

目前,我正在做一些像下面这样的事情,感觉有点繁琐:

run_once = 0
while 1:
    if run_once == 0:
        myFunction()
        run_once = 1:

我在想,处理这些事情有没有更好的方法呢?

我想要的是让一个函数在需要的时候只执行一次。比如说,按下某个按钮的时候。这个应用是互动式的,有很多用户可以控制的开关。为了跟踪每个开关是否已经运行,我不得不为每个开关设置一个无用的变量,这样做感觉有点低效。

19 个回答

6

在循环之前运行这个函数。举个例子:

myFunction()
while True:
    # all the other code being executed in your loop

这是一个显而易见的解决办法。如果事情比看起来的要复杂,解决方案可能会稍微复杂一些。

27

另一个选择是把你的函数的 func_code 设置为一个什么都不做的函数的代码对象。这一步应该在你的函数体的最后进行。

举个例子:

def run_once():  
   # Code for something you only want to execute once
   run_once.func_code = (lambda:None).func_code

这里的 run_once.func_code = (lambda:None).func_code 是把你函数的可执行代码替换成了一个什么都不做的代码,所以之后每次调用 run_once() 都不会有任何效果。

这种方法比起在 被接受的答案 中提到的装饰器方式灵活性要差一些,但如果你只想让一个函数执行一次,这种方法可能会更简洁。

152

我会在这个函数上使用一个装饰器,来记录它运行了多少次。

def run_once(f):
    def wrapper(*args, **kwargs):
        if not wrapper.has_run:
            wrapper.has_run = True
            return f(*args, **kwargs)
    wrapper.has_run = False
    return wrapper


@run_once
def my_function(foo, bar):
    return foo+bar

现在,my_function 这个函数只会运行一次。之后再调用它时,会返回 None。如果你想让它返回其他东西,只需在 if 后面加一个 else 条件。从你的例子来看,它其实不需要返回任何东西。

如果你不能控制这个函数的创建,或者这个函数需要在其他地方正常使用,你也可以手动应用这个装饰器。

action = run_once(my_function)
while 1:
    if predicate:
        action()

这样就可以让 my_function 在其他地方继续使用。

最后,如果你只想让它运行一次或两次,那你可以直接这样做:

action = run_once(my_function)
action() # run once the first time

action.has_run = False
action() # run once the second time

撰写回答