【问题标题】:Is there a python libary that lets you call a function inside a function wtihout creating a recursive stack是否有一个 python 库可以让您在函数内部调用函数而不创建递归堆栈
【发布时间】:2017-08-25 10:05:18
【问题描述】:

我正在尝试从一种状态切换到另一种状态。每个状态都由一个函数表示。我想处理函数内部的切换逻辑,而不是调用函数的主循环。是否有允许这种模式的python库。 比如:

def c(count):
    if count<10:
        a(count+1)
        print("dont' keep track of post-order printing")
    else:
        print("when count is reached, program should terminate")
def b(count):
    c(count):
def a(count):
    b(count)
a()

这只是一个示例,我正在尝试使用有限状态模式,其中逻辑位于转换 on_enter 方法中。基本上,机器会自动从一种状态转换到下一种状态,而无需使用 main_loop。

【问题讨论】:

  • 我可能会为此考虑协程
  • @user252046 递归有什么问题。为什么要“没有它”?
  • 我不希望程序在达到基本情况后回调。并且循环永远持续下去。我知道它可以通过调用函数的主循环来完成,但它会造成很多混乱。

标签: python transitions fsm


【解决方案1】:

transitions 具有有序转换以及 queued 转换,这可能是您正在寻找的。基本技巧是在处理相同的事件时调用相同的事件(使用finalize)。即使转换未成功,传递给finalize 的回调也会被处理(并非所有conditions 都返回True)。使用queued,transitions 不会立即处理事件,而是在当前处理的事件之后立即处理,这将防止大规模递归。

from transitions import Machine
import time


class Model(object):

    # initialise counter and counter limit
    def __init__(self):
        self.counter = 0
        self.limit = 5

    # will be called in every cycle and increase the counter
    def increase_counter(self):
        self.counter += 1
        print("Counter increased to ", self.counter)
        time.sleep(0.5)

    # will be called whenever a new state has been entered
    def reset_counter(self):
        self.counter = 0
        print("Counter reset; Current state is ", model.state)

    # this function returns whether the limit has already been reached
    def limit_reached(self):
        return self.counter >= self.limit

# initialising the previously defined model
model = Model()
# creating some state names
states = ['A', 'B', 'C', 'D']

# configuring the state machine:
# pass the model (for callbacks), pass the state names,
# disable auto_transitions since we will not need them
# set the initial state to 'A' and call a (currently) undefined
# model function 'next_state' after EVERY triggered event.
# 'queued' means that every transition is finished before the next event is handled
machine = Machine(model, states=states, auto_transitions=False,
                  queued=True, initial='A', finalize_event='next_state')

# now add ordered transitions: 
# Depending on the order of the passed state names,
# create transitions from each state 'n' to state 'n+1' called 'next_state'.
# 'prepare' each transition attempt by increasing the counter
# afterwards check the 'conditions' (is the counter limit reached)
# if all callbacks in 'conditions' return True, the transition
# is conducted and callbacks in 'after' are processed (counter reset)
machine.add_ordered_transitions(prepare='increase_counter', conditions='limit_reached',
                                after='reset_counter', trigger='next_state')

# model will go into an infinite loop; can be triggered in a thread
model.next_state()

您可以尝试减少increase_counter 中的睡眠计时器,以检查您是否会遇到递归错误(您不应该)。如果您将queued=False 设置为标准行为,您将或多或少立即遇到递归错误,因为所有机器触发器都会立即处理。

【讨论】:

    【解决方案2】:

    有 fn.tcor https://github.com/kachayev/fn.py/blob/master/README.rst#trampolines-decorator。但是该库似乎没有维护..您可能会在 Python 中寻找尾部优化...您可能会找到一些东西..

    【讨论】:

      【解决方案3】:

      我希望它可能符合您的期望

      def c(count):
          if count<10:
              print("don't keep track of post-order printing")
              c(count+1)
          else:
              print("when count is reached, program should terminate")
      

      输出:

      >>> c(1)
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      don't keep track of post-order printing
      when count is reached, program should terminate
      

      【讨论】:

        猜你喜欢
        • 2018-12-19
        • 2022-01-03
        • 1970-01-01
        • 1970-01-01
        • 2011-12-09
        • 2023-03-27
        • 1970-01-01
        • 2013-05-06
        • 2016-05-13
        相关资源
        最近更新 更多