目前,我正在做类似以下的事情,这很乏味:
run_once = 0
while 1:
if run_once == 0:
myFunction()
run_once = 1:
Run Code Online (Sandbox Code Playgroud)
我猜有一些更可接受的方式来处理这些东西?
我正在寻找的是按需执行一次函数.例如,按下某个按钮.它是一个交互式应用程序,具有许多用户控制的开关.每个交换机都有一个垃圾变量,只是为了跟踪它是否已经运行,似乎效率低下.
aar*_*ing 102
我会在函数上使用一个装饰器来处理它运行的次数.
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
Run Code Online (Sandbox Code Playgroud)
现在my_function只运行一次.其他调用将返回None.如果您希望它返回其他内容,只需添加一个else子句即可if.从您的示例中,它不需要返回任何内容.
如果您不控制函数的创建,或者函数需要在其他上下文中正常使用,您也可以手动应用装饰器.
action = run_once(my_function)
while 1:
if predicate:
action()
Run Code Online (Sandbox Code Playgroud)
这将留给my_function其他用途.
最后,如果你只需要运行两次,那么你就可以做到
action = run_once(my_function)
action() # run once the first time
action.has_run = False
action() # run once the second time
Run Code Online (Sandbox Code Playgroud)
j b*_*j b 17
另一种选择是设置func_code 代码对象为你的函数是一个什么也不做的函数代码对象.这应该在函数体的末尾完成.
例如:
def run_once():
# Code for something you only want to execute once
run_once.func_code = (lambda:None).func_code
Run Code Online (Sandbox Code Playgroud)
这里run_once.func_code = (lambda:None).func_code使用lambda:None的代码替换函数的可执行代码,因此所有后续调用都run_once()不会执行任何操作.
这种技术不如接受的答案中提出的装饰器方法灵活,但如果您只想运行一次,则可能更简洁.
在循环之前运行该函数.例:
myFunction()
while True:
# all the other code being executed in your loop
Run Code Online (Sandbox Code Playgroud)
这是显而易见的解决方案.如果不仅仅满足于眼睛,那么解决方案可能会更复杂一些.
我想到了另一种\xe2\x80\x94有点不寻常,但非常有效的\xe2\x80\x94方法来做到这一点,不需要装饰器函数或类。相反,它只使用可变关键字参数,这应该适用于大多数版本的 Python。大多数情况下,这些都是需要避免的,因为通常您不希望默认参数值从 call-to-call\xe2\x80\x94 更改,但在这种情况下可以利用这种能力并将其用作廉价存储机制。这是它的工作原理:
\n\ndef my_function1(_has_run=[]):\n if _has_run: return\n print("my_function1 doing stuff")\n _has_run.append(1)\n\ndef my_function2(_has_run=[]):\n if _has_run: return\n print("my_function2 doing some other stuff")\n _has_run.append(1)\n\nfor i in range(10):\n my_function1()\n my_function2()\n\nprint(\'----\')\nmy_function1(_has_run=[]) # Force it to run.\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\ndef my_function1(_has_run=[]):\n if _has_run: return\n print("my_function1 doing stuff")\n _has_run.append(1)\n\ndef my_function2(_has_run=[]):\n if _has_run: return\n print("my_function2 doing some other stuff")\n _has_run.append(1)\n\nfor i in range(10):\n my_function1()\n my_function2()\n\nprint(\'----\')\nmy_function1(_has_run=[]) # Force it to run.\nRun Code Online (Sandbox Code Playgroud)\n\n通过执行 @gnibbler 在他的答案中建议的操作并使用迭代器(在 Python 2.2 中引入),可以进一步简化这一点:
\n\nfrom itertools import count\n\ndef my_function3(_count=count()):\n if next(_count): return\n print("my_function3 doing something")\n\nfor i in range(10):\n my_function3()\n\nprint(\'----\')\nmy_function3(_count=count()) # Force it to run.\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\nmy_function1 doing stuff\nmy_function2 doing some other stuff\n----\nmy_function1 doing stuff\nRun Code Online (Sandbox Code Playgroud)\n
我假设这是一个你想要最多执行一次的动作,如果满足某些条件.由于您不会总是执行操作,因此无法在循环外无条件执行操作.如果你收到请求,就像懒惰地检索一些数据(并缓存它),但是否则不会检索它.
def do_something():
[x() for x in expensive_operations]
global action
action = lambda : None
action = do_something
while True:
# some sort of complex logic...
if foo:
action()
Run Code Online (Sandbox Code Playgroud)
有很多方法可以做你想做的事;但是,请注意,很可能 - 如问题中所述 - 您不必在循环内调用该函数。
如果你坚持在循环内调用函数,你也可以这样做:
needs_to_run= expensive_function
while 1:
…
if needs_to_run: needs_to_run(); needs_to_run= None
…
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75040 次 |
| 最近记录: |