【问题标题】:How to early return from within a helper function?如何从辅助函数中提前返回?
【发布时间】:2016-11-25 19:43:35
【问题描述】:

所以我认为我很聪明,DRY 从一堆类似的函数中删除了一堆通用代码,并将它们变成了在一个地方定义的辅助函数。 (见GitHub diff)这样他们就可以从一个地方进行修改。 (见another GitHub diff

原来是这样的

func_A(stuff):
    if stuff == guard_condition:
        return early
    things = boilerplate + stuff
    do A-specific stuff(things)
    return late

func_b(stuff):
    if stuff == guard_condition:
        return early
    things = boilerplate + stuff
    do B-specific stuff(things)
    return late

我把它改成了

_helper(stuff):
    if stuff == guard_condition:
        return early
    things = boilerplate + stuff
    return things

func_A(stuff):
    things = _helper(stuff)
    do A-specific stuff(things)
    return late

func_B(stuff):
    things = _helper(stuff)
    do B-specific stuff(things)
    return late

但后来我尝试了一下,发现由于我将早期返回(“守卫”?)移到了辅助函数中,它们当然不再工作了。现在我可以轻松地向原始函数添加一些代码来处理这些情况,但似乎没有办法做到这一点,除非再次将复杂性移回各个函数并重复。

处理这种情况最优雅的方法是什么?

【问题讨论】:

  • 哦,这就是装饰器的用途吗?
  • 啊但是如果要包装的函数带不同数量的参数,你需要在装饰器中使用*args,然后它就变成了函数签名,这很丑。

标签: python return helpers


【解决方案1】:

这有帮助吗?

 def common_stuff(f):
    def checked_for_guards(*args, **kwargs):
        if stuff == guard_condition:
            return early
        things = boilerplate
        else:
            return f(*args, **kwargs)
    return checked_for_guards

@common_stuff
def func_A(stuff):
    do A-specific stuff(things)
    return late

@common_stuff
def func_b(stuff):
    do B-specific stuff(things)
    return late

【讨论】:

  • 我没有想到的一件事是 func_A 和 func_B 采用不同数量的参数,但这意味着包装函数需要使用*args,然后它将成为函数的签名被包裹起来,这有点难看,所以我想我必须使用其他解决方案。
  • 以上代码适用于 func_a 和 func_b 的任何类型或参数。包装后的函数将其接收到的所有参数原样传递给 func_a 或 func_b。
【解决方案2】:

您可以将a-specific stuffb-specific stuff 提取到核心函数,然后传递给您的辅助函数。然后助手会决定是否调用核心函数:

_helper(stuff, _core_func):
    if stuff == guard_condition:
        return early
    things = boilerplate
    return _core_func(things)

_a_core(_things):
    do a-specific stuff
    return late

_b_core(_things):
    do b-specific stuff
    return late

func_A(stuff):
    return _helper(stuff, _a_core)

func_B(stuff):
    return _helper(stuff, _b_core)

在了解帮助者的返回值之前的早期答案

我会给_helper一个返回值:

_helper(stuff):
    if guard:
        return False
    boilerplate
    return True

func_a(stuff):
    if _helper():
        do a-specific stuff
    return

func_b(stuff):
    if _helper():
        do b-specific stuff
    return

【讨论】:

  • 嗯,它确实有一个返回值。我想我应该让我的示例更像实际代码
  • 您可以使用相同的原理。使返回值成为一个元组,其中添加的元素是 _helper 是通过早期返回路径还是完整路径。
  • 是的,但这就是我所说的“将复杂性添加回原始函数”的意思
  • 嗯,可以。不过,似乎还有更好的方法。
猜你喜欢
  • 2017-03-27
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 2019-08-02
  • 1970-01-01
  • 2019-05-05
  • 2022-10-07
相关资源
最近更新 更多