如何在Python中使用依赖关键字参数定义函数?

时间:2017-06-27 09:00:16

标签: python function arguments

我有一个带有1个位置参数和2个关键字参数的函数:

def foo(arg1, kw_arg1='Keyword Argument', kw_arg2='Keyword Argument'):
    print('The arguments are: {}, {}, {}'.format(arg1, kw_arg1, kw_arg2))

现在,我想要第二个关键字参数的默认值,即kw_arg2依赖于kw_arg1。更准确地说,我希望kw_arg2的值默认为kw_arg1,但不会传递给函数foo

该要求的函数原型将是:

def foo(arg1, kw_arg1='Keyword Argument', kw_arg2=kw_arg1):
    print('The arguments are: {}, {}, {}'.format(arg1, kw_arg1, kw_arg2))

但是,这在Python 3.6.0上运行时会导致NameError

基本解决方案

我通过将我的函数定义为:

找到了解决方法
def foo(arg1, kw_arg1='Keyword Argument', kw_arg2=None):
    if kw_arg2 is None:
        kw_arg2 = kw_arg1

    print('The arguments are: {}, {}, {}'.format(arg1, kw_arg1, kw_arg2))

但是,我发现这个实现有点限制,因为我隐含在陈述kw_arg1kw_arg2之间的关系。此外,我无法将kw_arg2设置为None

我想知道如何通过更明确的解决方法实现这一目标。

1 个答案:

答案 0 :(得分:0)

这样做的一种方法是使用**kwargs,并要求用户在需要时为函数提供kw_arg2作为关键字参数(即记录此!!)。

如果用户向None提供kw_arg2,则可以避免分崩离析。

这种方法的缺点是用户 提供kw_arg2作为关键字参数,并且不能仅依赖于提供位置参数,而且它不太明显通过查看函数定义,函数需要什么参数。

def foo(arg1, kw_arg1='Keyword Argument', **kwargs):
    """A function that does foo.

    Args:
        arg1: ...
        kw_arg1: ...
        kw_arg2: Will default to the value of kw_arg1 if no 
                 value is passed to this key word argument.
    """
    if 'kw_arg2' in kwargs:
        kw_arg2 = kwargs['kw_arg2']
    else:
        kw_arg2 = kw_arg1
    print('The arguments are: {}, {}, {}'.format(arg1, kw_arg1, kw_arg2))

如果你希望用户也能够传递kw_arg2作为位置参数,你可以尝试使用* args和** kwargs一些技巧,但当然这是你需要的东西小心并平衡潜在的滥用与利益:

def foo(arg1, kw_arg1='Keyword Argument', *args, **kwargs):
    """A function that does foo."""
    if 'kw_arg2' in kwargs:
        kw_arg2 = kwargs['kw_arg2']
    elif args:
        kw_arg2 = args[0]
    else:
        kw_arg2 = kw_arg1
    print('The arguments are: {}, {}, {}'.format(arg1, kw_arg1, kw_arg2))