Short-circuit evaluation like Python's "and" while storing results of checks
<p>I have multiple expensive functions that return results.  I want to return a tuple of the results of all the checks if all the checks succeed.  However, if one check fails I don't want to call the later checks, like the short-circuiting behavior of <code>and</code>.  I could nest <code>if</code> statements, but that will get out of hand if there are a lot of checks.  How can I get the short-circuit behavior of <code>and</code> while also storing the results for later use?</p>

<pre><code>def check_a():
    # do something and return the result,
    # for simplicity, just make it "A"
    return "A"

def check_b():
    # do something and return the result,
    # for simplicity, just make it "B"
    return "B"

...
</code></pre>

<p>This doesn't short-circuit:</p>

<pre><code>a = check_a()
b = check_b()
c = check_c()

if a and b and c:
    return a, b, c
</code></pre>

<p>This is messy if there are many checks:</p>

<pre><code>if a:
   b = check_b()

   if b:
      c = check_c()

      if c:
          return a, b, c
</code></pre>

<p>Is there a shorter way to do this?</p>

<p>You could use either a list or an OrderedDict, using a for loop would serve the purpose of emulating short circuiting.</p>

<pre><code>from collections import OrderedDict


def check_a():
    return "A"


def check_b():
    return "B"


def check_c():
    return "C"


def check_d():
    return False


def method1(*args):
    results = []
    for i, f in enumerate(args):
        value = f()
        results.append(value)
        if not value:
            return None

    return results


def method2(*args):
    results = OrderedDict()

    for f in args:
        results[f.__name__] = result = f()
        if not result:
            return None

    return results

# Case 1, it should return check_a, check_b, check_c
for m in [method1, method2]:
    print(m(check_a, check_b, check_c))

# Case 1, it should return None
for m in [method1, method2]:
    print(m(check_a, check_b, check_d, check_c))
</code></pre>

python short-circuiting