代码之家  ›  专栏  ›  技术社区  ›  Mark

获取函数内部的Kwargs

  •  18
  • Mark  · 技术社区  · 15 年前

    如果我有这样的python函数:

    def some_func(arg1, arg2, arg3=1, arg4=2):
    

    是否有方法确定哪些参数是通过关键字从函数内部传递的?

    编辑

    对于那些问我为什么需要这个的人,我没有真正的理由,它是在一次谈话中出现的,好奇心使我变得更好。

    5 回复  |  直到 15 年前
        1
  •  16
  •   Alex Martelli    15 年前

    不,用这个签名在Python代码中是不可能做到的——如果您需要这个信息,您需要更改函数的签名。

    如果您查看python c api,您将看到传递给普通python函数的参数的实际方式始终是作为一个元组加上一个dict——即,直接反映签名的方式 *args, **kwargs . 然后,该元组和dict被解析为特定的位置参数和在签名中命名的参数,即使它们是按名称传递的,并且 *a **kw 如果存在,只从解析中获得“溢出”,如果有的话——只有在此时,您的Python代码才得到控制,到那时您请求的信息( 怎样 各种参数是否通过)不再存在。

    因此,要获取您请求的信息,请将签名更改为 *a, **kw 做你自己的分析/验证——这是“从鸡蛋到煎蛋”,也就是说,一定量的工作,但肯定可行,而你要寻找的将是“从煎蛋到鸡蛋”…根本不可行;-)。

        2
  •  11
  •   awesomo    15 年前

    下面是我通过装饰师的解决方案:

    def showargs(function):
        def inner(*args, **kwargs):
            return function((args, kwargs), *args, **kwargs)
        return inner
    
    @showargs
    def some_func(info, arg1, arg2, arg3=1, arg4=2):
        print arg1,arg2,arg3,arg4
        return info
    
    In [226]: some_func(1,2,3, arg4=4)
    1 2 3 4
    Out[226]: ((1, 2, 3), {'arg4': 4})
    

    可能有一种方法可以进一步清除这个问题,但这对我来说似乎是最小的干扰,不需要更改调用代码。

    编辑: 要实际测试特定参数是否通过关键字传递,请在某些函数内执行如下操作:

    args, kwargs = info
    if 'arg4' in kwargs:
        print "arg4 passed as keyword argument"
    

    免责声明: 您可能应该考虑是否真正关心这些参数是如何传递的。整个方法可能是不必要的。

        3
  •  3
  •   Mike DeSimone    15 年前

    你必须重新定义你的功能:

    def some_func(*args, **kwargs):
    

    你自己去整理一下。没有办法区分传递位置、传递关键字和默认值之间的区别。

        4
  •  1
  •   poke    15 年前

    就这样做:

    def some_func ( arg1, arg2, arg3=None, arg4=None ):
        if arg3 is None:
            arg3 = 1 # default value
        if arg4 is None:
            arg4 = 2 # default value
    
        # do something
    

    这样你就可以看到什么东西被设置好了, 您还可以使用更复杂的默认结构(如列表),而不会遇到以下问题:

    >>> def test( arg=[] ):
            arg.append( 1 )
            print( arg )
    >>> test()
    [1]
    >>> test()
    [1, 1]
    
        5
  •  1
  •   SilentGhost    15 年前

    你想知道 arg3 1 因为它是从外部传递的还是因为它是默认值?不,据我所知,没有办法做到这一点。我想,最主要的原因是不需要这样的知识。通常要做的是:

    >>> def func(a, b=None):
        if b is None:
    # here we know that function was called as:
    # func('spam') or func('spam', None) or func('spam', b=None) or func(a='spam', b=None)
    
            b = 42