返回值满足某些条件

返回值满足某些条件

本文介绍了在返回值满足某些条件之前,如何调用函数序列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时候我发现自己在写这样的代码:

Sometimes I find myself writing code like this:

def analyse(somedata):
    result = bestapproach(somedata)
    if result:
        return result
    else:
        result = notasgood(somedata)
        if result:
            return result
        else:
            result = betterthannothing(somedata)
            if result:
                return result
            else:
                return None

那太丑了。当然,有些人喜欢省略某些语法:

That's pretty ugly. Of course, some people like to leave off some of that syntax:

def analyse(somedata):
    result = bestapproach(somedata)
    if result:
        return result
    result = notasgood(somedata)
    if result:
        return result
    result = betterthannothing(somedata)
    if result:
        return result

但这并没有太大的改善;这里仍然有大量重复的代码,而且仍然很丑陋。

But that's not much of an improvement; there's still a ton of duplicated code here, and it's still ugly.

我研究了使用带有定点值的内置 iter(),但在这种情况下, None 值用于表示该循环应继续进行,而不是用于指示该循环应终止的哨兵。

I looked into using the built-in iter() with a sentinel value, but in this case the None value is being used to signal that the loop should keep going, as opposed to a sentinel which is used to signal that the loop should terminate.

Python中是否还存在其他(健全)技术来实现这种不断尝试,直到找到有用的东西模式?

Are there any other (sane) techniques in Python for implementing this sort of "keep trying until you find something that works" pattern?

I应该阐明返回值满足某些条件不限于示例中条件为且bool(result)为True 的情况。可能的分析功能列表中的每一个都会产生一些衡量成功程度的系数(例如R平方值),并且您想要设置接受的最小阈值。因此,通用解决方案不应固有地依赖于结果的真实值。

I should clarify that "return value meets some condition" is not limited to cases where the condition is if bool(result) is True as in the example. It could be that the list of possible analysis functions each produce some coefficient measuring the degree of success (e.g. an R-squared value), and you want to set a minimum threshold for acceptance. Therefore, a general solution should not inherently rely on the truth value of the result.

推荐答案

Option #1:使用



当总函数数是a)已知,b)小,并且测试条件完全基于收益率的真值,可以按照Grapsus的建议简单地使用

d = 'somedata'
result = f1(d) or f2(d) or f3(d) or f4(d)

因为,这些函数从右到左执行,直到其中一个产生返回值为 True ,这时将分配给 result ,并且不评估其余函数;或直到函数用尽,然后为结果分配了 False

Because Python's boolean operators short-circuit, the functions are executed from right to left until one of them produces a return value evaluated as True, at which point the assignment is made to result and the remaining functions are not evaluated; or until you run out of functions, and result is assigned False.

当总函数数为a)未知,或b )非常大,一种单行生成器生成方法可以工作,如Bitwise建议的那样:

When the number of total functions is a) unknown, or b) very large, a one-liner generator comprehension method works, as Bitwise suggested:

result = (r for r in (f(somedata) for f in functions) if <test-condition>).next()

与选项#1相比,它还有一个额外的优势,即您可以使用任何您想要的< test-condition> ,而不仅依赖于真值。每次调用 .next()

This has the additional advantage over option #1 that you can use any <test-condition> you wish, instead of relying only on truth value. Each time .next() is called:


  1. 我们要求外部发生器提供其下一个元素

  2. 外部生成器向内部生成器询问其下一个元素

  3. 内部生成器向其询问 f 函数尝试计算 f(somedata)

  4. 如果可以对表达式求值(即 f 是一个函数,而 somedata 是有效的加法),内部生成器向外部生成器返回 f(somedata)的返回值

  5. 如果< test -condition> 满足,外部生成器产生 f(somedata)的返回值,并将其分配为 result

  6. 如果在步骤5中不满足< test-condition>

  1. We ask the outer generator for its next element
  2. The outer generator asks the inner generator for its next element
  3. The inner generator asks for an f from functions and tries to evaluate f(somedata)
  4. If the expression can be evaluated (i.e., f is a function and somedata is a valid arugment), the inner generator yields the return value of f(somedata) to the outer generator
  5. If <test-condition> is satisfied, the outer generator yields the return value of f(somedata) and we assign it as result
  6. If <test-condition> was not satisfied in step 5, repeat steps 2-4

此方法的一个缺点是嵌套的理解不如其多行等效项直观。另外,如果内部生成器已用尽而又不满足测试条件,则 .next()会引发 StopIteration

A weakness of this method is that nested comprehensions can be less intuitive than their multi-line equivalents. Also, if the inner generator is exhausted without ever satisfying the test condition, .next() raises a StopIteration which must be handled (in a try-except block) or prevented (by ensuring the last function will always "succeed").

由于我们可以将可调用函数放在列表中,因此一个选项是在列表中显式列出要尝试的函数。使用它们的顺序,然后遍历该列表:

Since we can place callable functions in a list, one option is to explicitly list the functions you want to "try" in the order they should be used, and then iterate through that list:

def analyse(somedata):
    analysis_functions = [best, okay, poor]
    for f in analysis_functions:
        result = f(somedata)
        if result:
            return result

优点:修复了重复代码的问题,很显然,您正在执行迭代过程,并且短路(不会继续执行)在找到好结果后运行)。

Advantages: Fixes the problem of repeated code, it's more clear that you're engaged in an iterative process, and it short-circuits (doesn't continue executing functions after it finds a "good" result).

这也可以用Python的 for ... else 语法编写:*

This could also be written with Python's for ... else syntax:*

def analyse(somedata):
    analysis_functions = [best, okay, poor]
    for f in analysis_functions:
        result = f(somedata)
        if result:
            break
    else:
        return None
    return result

这里的优点是可以识别退出函数的不同方法,如果您希望 analyse()函数完全失败,这可能很有用。返回 None 以外的值,或引发异常。否则,它就会变得更长且更深奥。

The advantage here is that the different ways to exit the function are identified, which could be useful if you want complete failure of the analyse() function to return something other than None, or to raise an exception. Otherwise, it's just longer and more esoteric.

*如,从@ 15:50开始。

*As described in "Transforming Code into Beautiful, Idiomatic Python", starting @15:50.

这篇关于在返回值满足某些条件之前,如何调用函数序列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 13:31