简体   繁体   English

处理不同的,互斥的函数输入的最Python方式是什么?

[英]What’s the most Pythonic way of handling different, mutually-exclusive function inputs?

I am trying to find a clean way to handle different, mutually-exclusive function inputs. 我试图找到一种处理不同的,互斥的函数输入的干净方法。 The idea is that I have a function which returns 4 values (these values are linked through mathematical equations), and when you input one of the 4 values, it returns all the values. 我的想法是,我有一个返回4个值的函数(这些值通过数学方程式链接),当您输入4个值之一时,它将返回所有值。

Currently the function works like this: 当前该函数的工作方式如下:

#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

The user specifies what the input variable is by means of a string vtype, and it returns all the values. 用户通过字符串vtype指定输入变量是什么,并返回所有值。 It is not possible for the user to input more than one different input value (would be redundant, because all the unknowns can be determined from one input value). 用户不可能输入一个以上的不同输入值(这是多余的,因为所有未知数都可以从一个输入值中确定)。

Is there a more clean and pythonic way to do this? 有没有更干净和pythonic的方法来做到这一点? Specifying the input variable with a string feels really dirty at the moment. 现在,用字符串指定输入变量确实很脏。

Thanks in advance! 提前致谢!

You could use variable keyword arguments: 您可以使用可变关键字参数:

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

Then use with named parameters: 然后使用命名参数:

relations(a=2)
relations(b=4)
relations(c=9)
relations(d=0)

A common approach to avoid many if - elif s is to build a dictionary of functions: 避免许多if - elif的常见方法是构建函数字典:

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

If this function is not a bottleneck you can avoid using the lambda s and simply do: 如果此功能不是瓶颈 ,则可以避免使用lambda ,只需执行以下操作:

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

If you don't like the idea of having vtype in the function signature you can use a single **kwargs argument: 如果您不喜欢在函数签名中使用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

Then call it as: 然后将其称为:

relations(a=...)
relations(b=...)

You can define your vtypes as functions, and pass the function as parameter 您可以将vtypes定义为函数,并将函数作为参数传递

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

With that you can get rid of the if / elif too. 有了它,您也可以摆脱if / elif

You could use something like this: 您可以使用如下形式:

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

Then you can use the function simply with eg relations(c=10) or relations(a=2) . 然后,您可以简单地将函数与relations(c=10)relations(a=2) So you don't need the vtype argument. 因此,您不需要vtype参数。

The first passed argument is used to calculate a . 第一传递的参数被用于计算a If you call the function with more than one argument only the first will be used and the others will be ignored (eg relations(b=2, c=5) only b will be used and c is ignored). 如果您使用多个参数调用该函数,则仅会使用第一个参数,而其他参数将被忽略(例如, relations(b=2, c=5)仅会使用bc被忽略)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM