1

我试图找到一种干净的方法来处理不同的、互斥的函数输入。这个想法是我有一个返回 4 个值的函数(这些值通过数学方程链接),当您输入 4 个值之一时,它会返回所有值。

目前该功能的工作方式如下:

#example relations are simply: b=1+a, c=0.5*a, d=sqrt(a)
def relations(v, vtype="a"):
    if vtype=="a":
        a = v
    elif vtype=="b":
        a = v - 1
    elif vtype=="c":
        a = 2 * v
    elif vtype=="d":
        a = v ** 2

    b = 1 + a
    c = 0.5 * a
    d = a ** 0.5

    return a,b,c,d

用户通过字符串 vtype 指定输入变量是什么,并返回所有值。用户不可能输入多个不同的输入值(这将是多余的,因为所有未知数都可以从一个输入值确定)。

有没有更干净和pythonic的方式来做到这一点?目前用字符串指定输入变量感觉真的很脏。

提前致谢!

4

4 回答 4

2

避免 many if- elifs 的常用方法是构建函数字典:

def relations(v, vtype='a'):
    functions = {
        'a': lambda x: x, 'b': lambda x: x-1,
        'c': lambda x: x * 2, 'd': lambda x: x**2
    }

    a = functions[vtype](v)
    b = 1 + a
    c = 0.5 * a
    d = a ** 0.5
    return a,b,c,d

如果此功能不是瓶颈,您可以避免使用lambdas 并简单地执行以下操作:

values = {'a': v, 'b': v-1, 'c': v * 2, 'd': v**2}
a = values[vtype]

如果您不喜欢vtype在函数签名中包含的想法,您可以使用单个**kwargs参数:

def relations(**kwargs):
    if len(kwargs) != 1 or not set('abcd').intersection(kwargs):
        raise ValueError('Invalid parameters')
    vtype, v = kwargs.popitem()
    functions = {
        'a': lambda x: x, 'b': lambda x: x-1,
        'c': lambda x: x * 2, 'd': lambda x: x**2
    }

    a = functions[vtype](v)
    b = 1 + a
    c = 0.5 * a
    d = a ** 0.5
    return a,b,c,d

然后将其称为:

relations(a=...)
relations(b=...)
于 2013-07-04T08:47:33.047 回答
2

您可以使用可变关键字参数:

def relations(**kwargs):
    if 'a' in kwargs:
        a = kwargs['a']
    elif 'b' in kwargs:
        a = kwargs['b'] - 1
    elif 'c' in kwargs:
        a = kwargs['c'] * 2
    elif 'd' in kwargs:
        a = kwargs['d'] ** 2
    else:
        raise TypeError('missing an argument')

    b = 1 + a
    c = 0.5 * a
    d = a ** 0.5

    return a, b, c, d

然后使用命名参数:

relations(a=2)
relations(b=4)
relations(c=9)
relations(d=0)
于 2013-07-04T08:25:29.827 回答
1

您可以将 vtype 定义为函数,并将函数作为参数传递

def a(v):
    return v

def b(v):
    return v-1

def c(v):
    return 2*v

def d(v):
    return v**2

def relations(v, vtype=a):
    value_a = vtype(v)
    value_b = 1 + value_a
    value_c = 0.5 * value_a
    value_d = value_a ** 0.5
    return value_a,value_b,value_c,value_d

有了它,您也可以摆脱if/ elif

于 2013-07-04T08:33:13.057 回答
0

你可以使用这样的东西:

def relations(a=None, b=None, c=None, d=None):
    if a is not None:
        pass
    elif b is not None:
        a = b - 1
    elif c is not None:
        a = 2 * c
    elif d is not None:
        a = d ** 2
    else:
        raise TypeError('At least one argument needed')

    # your calculations

然后您可以简单地使用该功能,例如relations(c=10)relations(a=2)。所以你不需要vtype论证。

第一个传递的参数用于计算a. 如果您使用多个参数调用函数,则仅使用第一个参数,而忽略其他参数(例如,relations(b=2, c=5)b使用并c忽略)。

于 2013-07-04T08:20:40.867 回答