首页 > 解决方案 > Python可能会短路函数调用

问题描述

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

我想构建一个函数,允许用户通过函数调用附加其他属性。重要的是,我想找到一种“短路”参数的方法,并且不确定 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。此外,如果详细设置为 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))

但是,我希望在没有分支的情况下实现这种行为。

标签: pythonreflectioninspect

解决方案


这并不能完全回答捷径点,但这是一种更有效的编写方式:

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,并动态添加到字典中。


推荐阅读