Python可能会短路函数调用

时间:2018-08-20 22:34:14

标签: python reflection inspect

我正在构建一个函数来构造具有设置属性的对象(类似于namedtuple);但是,输出长度必须可变。

我想构建一个函数,该函数允许用户通过函数调用附加其他属性。重要的是,我想找到一种方法来“短路”参数,并且不确定Python是否足够强大来做到这一点。

以这个简单的例子来解释:

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

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

if foo() and bar():
    pass

Foo的函数调用返回False,并且Bar短路。输出控制台将仅打印foo,并且不会执行 bar

是否存在通过检查或反映函数调用来模仿此行为的方法。这是我的实现示例,如下所示:

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))

在函数“ stats”中,返回fooFormat当然应该产生avg,lowerB和upperB;此外,如果将verbose设置为True,它应该产生std。此外,如果将verbose设置为False,则不应调用函数'stdev'。

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

当然,解决此问题的方法是:

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))

但是,我希望在那里实现这种行为而无需分支。

1 个答案:

答案 0 :(得分:1)

这并不能完全解决快捷方式问题,但这是一种更有效的编写方式:

out_dic = {                      # these items will always be calculated
   'avg':   avg,
   'lowerB':max(nums),
   'upperB':min(nums)
}
if verbose:                      # this is calculated only if verbose
    out_dic['stdev'] = stdev(nums,avg)

return fooFormat(**out_dic)

换句话说,您可以将字典扩展到kwargs,然后动态添加到字典中。