lundi 20 août 2018

Python possible to short circuit function call

I am building a function to construct objects with set attributes (similar to a namedtuple); however, the output length must be variable.

I would like to build a function that allows the user to append additional attributes through a function call. Importantly, I would like to find a way to 'short-circuit' parameters and am unsure if Python is powerful enough to do this.

To explain take this trivial example:

def foo():
    print("foo")
    return False

def bar():
    print("bar")
    return True

if foo() and bar():
    pass

Foo's function call returns False, and Bar short-circuits. The output console will only print foo, and bar is never executed.

Is there such a way to mimic this behavior with inspection or reflection in respect to function calls. Here is an example with my implementation is shown below:

from inspect import stack

cache = {}
def fooFormat(**kwargs):
    caller = stack()[1][3]

    if caller not in cache:
        class fooOut(object):
            def __init__(self, **kwargs):
                self.__dict__.update(kwargs)

            def optional(self, opt, **kwargs):
                if (opt):
                    self.__dict__.update(kwargs)
                return self

            def __str__(self):
                return caller + str(self.__dict__)
        cache[caller] = iadsOut
    return cache[caller](**kwargs)

def stdev(nums, avg = None):
    print("\tStdev call")
    if avg is None:
        avg = sum(nums) / len(nums)

    residuals = sum((i - avg)**2 for i in nums)
    return residuals**.5

def stats(nums, verbose=False):
    if verbose:
        print("Stats call with verbose")
    else:
        print("Stats call without verbose")

    total = sum(nums)
    N = len(nums)
    avg = total / N

    return fooFormat(
        avg = avg,
        lowerB = min(nums),
        upperB = max(nums)).optional(verbose,
        stdev = stdev(nums, avg))

In the function 'stats', the return fooFormat should of course yield avg, lowerB, and upperB; additionally, it should yield std if verbose is set to True. Moreover, the function 'stdev' should NOT be called if verbose is set to False.

stats([1,2,3,4], False)
stats([1,2,3,4], True)

Of course, a way around this is:

if verbose:
    return fooFormat(
        avg = avg,
        lowerB = min(nums),
        upperB = max(nums),
        stdev = stdev(nums, avg))
else:
    return fooFormat(
        avg = avg,
        lowerB = min(nums),
        upperB = max(nums))

However, I am hoping there to implement this behavior without a branch.





Aucun commentaire:

Enregistrer un commentaire