【问题标题】:Python: put all function arguments into **kwargs automaticallyPython:将所有函数参数自动放入 **kwargs
【发布时间】:2015-10-08 18:23:36
【问题描述】:

说明

假设我有以下函数,它调用另一个函数:

def f1(arg1, arg2, arg3):
    f2(...)

f1f2 的参数相同,或者f2 可能如下所示:

def f2(**kwargs)
    pass  # whatever

客户端代码要定义并调用f1,要求f1的签名明确定义所有参数,因此**kwargs不允许f1

所以,要从f1 内部调用f2,我必须这样做:

def f1(arg1, arg2, arg3):
    f2(arg1, arg2, arg3)

问题

有没有一种方法可以将参数传递给f2 而无需显式编写它们?理想情况下,我认为它应该是这样的:

def f1(arg1, arg2, arg3):
        kwargs = <Some Magic Here>
        f2(**kwargs)

有什么魔法吗?

更新

可能的解决方案

有没有办法可以结合locals()inspect.getargspec() 来聚合我的**kwargs

【问题讨论】:

    标签: python reflection arguments inspect


    【解决方案1】:

    一般情况

    好吧,您可以创建kwargs 作为f2() 接受并传递它的所有参数的字典。虽然我没有看到任何好处,但使用 -

    def f1(arg1, arg2, arg3):
        f2(arg1=arg1, arg2=arg2, arg3=arg3)
    

    对我来说看起来不错,并且比构建字典并将其称为 **kwargs 更容易。

    无论如何,这样做的方法是-

    >>> def a(a,b,c):
    ...     kwargs = {'a':a , 'b':b , 'c':c}
    ...     d(**kwargs)
    ...
    >>> def d(**kwargs):
    ...     print(kwargs)
    ...
    >>> a(1,2,3)
    {'c': 3, 'a': 1, 'b': 2}
    

    适合您的用例

    问题是f1要由客户端定义,参数的处理是通用的,所以我想隐藏处理细节,让客户端将所有参数传递给实现。此外,我想简化定义并自动传递所有参数,而不是明确指定它们。

    locals() 在函数内部将当时函数中局部变量的副本作为字典返回给您。如果在您的问题中 f1()f2() 的定义相同,您可以使用 locals() ,在任何其他代码之前在函数开头调用它。示例 -

    >>> def a(a,b,c):
    ...     lcl = locals()
    ...     print(lcl)
    ...     d(**lcl)
    ...     e = 123
    ...     print(locals())
    ...
    >>> def d(**kwargs):
    ...     print(kwargs)
    ...
    >>> a(1,2,3)
    {'c': 3, 'a': 1, 'b': 2}
    {'c': 3, 'a': 1, 'b': 2}
    {'c': 3, 'a': 1, 'e': 123, 'lcl': {...}, 'b': 2}
    

    【讨论】:

    • 感谢您的回答。我已经更新了我的问题。问题是f1 将由客户端定义,参数的处理是通用的,所以我想隐藏处理细节,以便客户端将所有参数传递给实现。此外,我想简化定义并自动传递所有参数而不是明确指定它们。
    • 这种情况下可以使用locals()
    • a 我可以打电话给d,在d 我可以得到a,它是locals 使用inspect。使用inspect.getargspec 额外验证locals 是否有意义?
    • 你不需要那个,因为字典 kwargs in d 打印,你只得到来自 a 的参数,因为它在字典 kwargs in d 中。
    • 您可以遍历kwargs 字典以获取其中的参数。
    【解决方案2】:

    这是我根据Anand S Kumar's answerAlex Martelli's answer to another question 解决问题的方法:

    def f2():
        kwargs = inspect.getouterframes(inspect.currentframe(), 2)[1][0].f_locals
        print(kwargs)
    
    def f1(arg1, arg2, arg3)
        f2()  # this should be called right at the first line
    
    >>> f1(1, 2, 3)
    {'arg1': 1, 'arg2': 2, 'arg3': 3}
    

    【讨论】:

      【解决方案3】:

      你想要的是将父函数的参数传递给一个封闭函数。所以首先我必须说你不能使用local(),因为local包含包含参数的局部变量和所有局部变量您在函数伙伴中定义的变量,但如果您只想在动态时获取所有参数并且像您的示例一样,我建议在父函数中使用*args

      def f1(*args):
      

      但这里有一点,因为你想使用**kwargs,它是为了收集你需要的任意关键字参数来作为参数的初始名称。

      例如,您可以使用如下的 dict 理解:

      def f1(*args):
              kwargs = {'arg{}'.format(i):j for i,j in enumerate(args,1)}
              f2(**kwargs)
      

      此外,如果您确定在定义封闭函数之前您的函数伙伴中没有局部变量,您可以使用locals

      例子:

      >>> globsl_a=8
      >>> def fun(arg1,arg2,arg3):
      ...   print locals()
      ... 
      >>> fun(5,[3,4],'text')
      {'arg1': 5, 'arg2': [3, 4], 'arg3': 'text'}
      >>> 
      

      【讨论】:

      • 您对locals() 的看法是正确的,但是在函数的开头调用locals() 是可以的,在这种情况下,我想它只会包含参数,我是对的吗?至于用*args定义f1,我不想这样做,为了代码完成。
      • 非常感谢@Kasra,但Anand S Kumar's answer 更适合我。
      猜你喜欢
      • 1970-01-01
      • 2012-04-09
      • 2015-01-28
      • 1970-01-01
      • 2022-12-01
      • 2023-04-06
      • 2016-02-16
      • 2021-02-04
      • 2012-12-09
      相关资源
      最近更新 更多