简体   繁体   English

是否可以将相同的可选参数传递给多个函数?

[英]Is it possible to pass the same optional arguments to multiple functions?

I want to ask if there is a way to prevent unnecessary duplicate of code when passing the same arguments into a function's optional arguments.我想问一下,在将相同的参数传递给函数的可选参数时,是否有办法防止不必要的代码重复。

Hopefully the following example provides a good idea of what I am trying to do:希望以下示例可以很好地了解我正在尝试做的事情:

def f(arg1):
    def g(optional_1=0, optional_2=0, optional_3=0):
        return arg1+optional_1+optional_2+optional_3
    return g

b, c = 2, 3
f1 = f(1)
f2 = f(2)
calc_f1 = f1(optional_2=b, optional_3=c)
calc_f2 = f2(optional_2=b, optional_3=c)

As you can see, f1 and f2 only differ in the arg1 passed into f and afterwards I call them with the same variables for the same optional arguments.如您所见,f1 和 f2 仅在传递给 f 的 arg1 中有所不同,然后我使用相同的变量调用它们以获取相同的可选参数。 It is fine when the code is short, but when I have over 10 optional arguments, it becomes unnecessarily long and redundant.当代码很短时很好,但是当我有超过 10 个可选参数时,它变得不必要地冗长和多余。 Is it possible to do something like是否有可能做类似的事情

optional_variable_pair = #some way to combine them
calc_f1 = f1(optional_variable_pair)
calc_f2 = f2(optional_variable_pair)

so I get a more succinct and easy to read code?所以我得到了一个更简洁易读的代码?

Any function with multiple optional arguments is a bit smelly because:任何带有多个可选参数的函数都有点臭,因为:

  1. you get so many argument combinations that it requires a large amount of testing.你得到了太多的参数组合,需要大量的测试。
  2. because of all the options the function has to have alot of conditionals and routes which increase its cyclomatic complexity.由于所有选项,该函数必须具有许多条件和路由,这会增加其圈复杂度。

You can apply a refactoring to extract the whole argument list into an Object and have the function work on that object.您可以应用重构将整个参数列表提取到一个对象中,并使该函数在该对象上工作。 This works really well if you can find a unifying name that describes your argument list and fits whatever metaphor you are using around the function.如果您能找到一个统一的名称来描述您的参数列表并适合您在函数周围使用的任何隐喻,那么这非常有效。 You can even invert the call so that the function becomes a method of the Object, so you get some encapsulation.您甚至可以反转调用,使函数成为对象的方法,从而获得一些封装。

To answer the question you asked, the answer is yes.要回答你提出的问题,答案是肯定的。 You can do almost exactly what you want using keyword argument unpacking.您几乎可以使用关键字参数解包来完成您想要的操作。

def f(arg1):
    def g(optional_1=0, optional_2=0, optional_3=0):
        return arg1+optional_1+optional_2+optional_3
    return g

optional_variable_pair = {
    'optional_2': 2,
    'optional_3': 3
}

f1 = f(1)
f2 = f(2)
calc_f1 = f1(**optional_variable_pair)
calc_f2 = f2(**optional_variable_pair)

If I'm reading your intent correctly, though, the essence of your question is wanting to pass new first arguments with the same successive arguments to a function.但是,如果我正确地阅读了您的意图,那么您的问题的本质是希望将具有相同连续参数的新第一个参数传递给函数。 Depending on your use case, the wrapper function g may be unnecessary.根据您的用例,包装函数g可能是不必要的。

def f(arg1, *, optional_1=0, optional_2=0, optional_3=0):
    return optional_1 + optional_2+optional_3

optional_variable_pair = {
    'optional_2': 2,
    'optional_3': 3
}

calc_f1 = f(1, **optional_variable_pair)
calc_f2 = f(2, **optional_variable_pair)

Obviously, if the first argument continues incrementing by one, a for loop is in order.显然,如果第一个参数继续递增,则for循环是有序的。 Obviously, if you are never using the optional_1 parameter, you do not need to include it.显然,如果您从不使用optional_1参数,则不需要包含它。 But, moreover, if you find yourself using numbered arguments, there is a good chance you really should be working with tuple unpacking instead of keyword unpacking:但是,此外,如果您发现自己使用编号参数,那么您很有可能真的应该使用元组解包而不是关键字解包:

def f(*args):
    return sum(args)

optional_variable_pair = (2, 3)

for i in range(1, 3):
    calc = f(i, *optional_variable_pair)
    # ...do something with calc...

You may also be interested in researching functools.partial , as well, which can take the place of your wrapper function g , and allow this:您可能也对研究functools.partial感兴趣,它可以代替您的包装函数g ,并允许:

import functools

def f(*args):
    return sum(args)

f1 = functools.partial(f, 1)
f2 = functools.partial(f, 2)

calc_f1 = f1(2, 3) # = 1 + 2 + 3 = 6
calc_f2 = f2(2, 3) # = 2 + 2 + 3 = 7

You use key-value pairs as function argsuments, for this purpose you can use *args and **kwargs:您使用键值对作为函数参数,为此您可以使用 *args 和 **kwargs:

optional_variable_pair = {
  "optional_1": 1,
  "optional_2": 2,
  "optional_3": 3,
}
calc_f1 = f1(**optional_variable_pair)
calc_f2 = f2(**optional_variable_pair)

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

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