获取传递给函数的参数的列表/元组/字典?


77

赋予以下功能:

def foo(a, b, c):
    pass

一个人如何获得传入的参数的列表/元组/ dict / etc,而不必自己构建结构

具体来说,我在寻找Python版本的JavaScriptarguments关键字或PHPfunc_get_args()方法。

不需要的是使用*argsor的解决方案**kwargs。我需要在函数定义中指定参数名称(以确保将其传递),但是在函数中,我想以列表或dict样式的结构使用它们。


1
请不要这样做。通过使用完美的关键字参数创建一个无用的字典,维护代码的人绝对会感到困惑。他们将被迫重写以删除字典。
S.Lott


@blahdiblah这个问题问的是如何获取参数本身,而不是参数名称。我不认为这是重复的。
安德森·格林

8
@ S.Lott:这是一个狭narrow的观点。有时,人们想在函数内部构建一个词典,并用一些强制性参数进行初始化。函数参数列表使它们很清楚,并且相信我,它们不一定是“无用的”。请参考Python的DRY原理,不要像我曾经工作过的一些初级开发人员那样,谁会抱怨“为什么有人要这么做?” 当我建议他们的API可能更通用时。
Michael Scheper

Answers:


94

您可以locals()用来获取函数中局部变量的字典,如下所示:

def foo(a, b, c):
    print locals()

>>> foo(1, 2, 3)
{'a': 1, 'c': 3, 'b': 2}

但是,这有点骇人听闻,因为它会locals()返回本地范围内的所有变量,而不仅是传递给函数的参数,因此,如果不在函数的顶部调用它,结果可能会包含比所需更多的信息。 :

def foo(a, b, c):
    x = 4
    y = 5
    print locals()

>>> foo(1, 2, 3)
{'y': 5, 'x': 4, 'c': 3, 'b': 2, 'a': 1}

如其他答案中所建议的那样,我宁愿在函数顶部构造一个字典或所需变量的列表。它更加明确,以更清晰的方式传达您的代码意图,恕我直言。


8
谢谢。对于希望使用此方法的其他任何人,请记住,您应该locals()在函数定义之后直接使用它,否则它将包含函数内定义的所有变量。
菲利普·奥德汉

3
值得注意的是,它locals()返回局部变量的快照,而不是指向某些内置字典的指针。因此,如果稍后定义变量或在函数中更改参数,locals()则分配给它的任何内容都不会更改。这就是你想要的。(I💜Python。)
Michael Scheper

2
还有趣的是,如果在方法中使用locals(),则字典中的键之一就是“ self”。因此,请确保对此进行更正/说明。
2016年

9

您可以使用检查模块:

def foo(x):
    return x

inspect.getargspec(foo)
Out[23]: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)

这是thisthis的重复。


3
您不能在函数中执行此操作,可以吗?
user2678074

5

如果参数不符合预期,我会使用*args**kwargs引发异常

如果您想要与python检查的错误相同的错误,可以执行类似的操作

def check_arguments(function_name,args,arg_names):
    missing_count = len(arg_names) - len(args)
    if missing_count > 0:
        if missing_count == 1:
            raise TypeError(function_name+"() missing 1 required positionnal argument: "+repr(arg_names[-1]))
        else:
            raise TypeError(function_name+"() missing "+str(missing_count)+" required positionnal argument: "+", ".join([repr(name) for name in arg_names][-missing_count:-1])+ " and "+repr(arg_names[-1]))

与某物一起使用

def f(*args):
    check_arguments("f",args,["a","b","c"])
    #whatever you want
    ...

2
这将需要在方法主体中进行大量测试,而将参数定义为函数的一部分将导致类似的错误,而无需任何其他测试。
菲利普·奥德汉



0

您已在标题中指定参数了吗?

您为什么不在体内简单地使用相同的信息?

def foo(a, b, c):
   params = [a, b, c]

我错过了什么?


4
这与我正在寻找的JavaScriptarguments或PHP不太相似func_get_args()
菲利普·奥德汉

我明白那个。缺少的是为什么您想要这样的功能。使用您已有的信息有什么问题?
奇怪的想

1
他可能希望将其抽象为一个,因此他编写了一个与ALL函数一起使用的助手,而不必始终手动编写每个参数。例如log_methods_arguments(arguments)
Hejazzman 2015年

@Nikos:您的log_methods_arguments示例可以使用*args, **kwargs参数。OP指出必须指定确切的参数。此代码气味的动机尚不清楚。
奇怪的想

1
log_methods_arguments带有* args,** kwargs不会改变任何东西。您仍然需要从要记录的方法(调用log_method_arguments的方法)中获取参数列表。
Hejazzman 2015年

0

您可以使用以下方法从其中创建一个列表:

args = [a,b,c]

您可以使用以下方法轻松地从中创建一个元组:

args =(a,b,c)

1
这与我正在寻找的JavaScriptarguments或PHP不太相似func_get_args()
菲利普·奥德

0
class my_class():
        compulsory_default_kwargs = {'p':20,'q':30,'r':40}
        formal_args_names = ['var1','var2']
        def __init__(self,*args,**kwargs):
            for key , value in locals().items():
                if((key == 'args')):
                    if(len(args) == len(my_class.formal_args_names)):
                        for key_name , arg_value in zip(my_class.formal_args_names,args):
                            setattr(self,key_name,arg_value)
                    else:
                        raise Exception ('Error - Number of formal arguments passed mismatched required {} whereas passed {}'.format(len(my_class.formal_args_names),len(args)))

                elif((key == 'kwargs') & (len(kwargs)!=0)):
                    for kw_key , kw_value in kwargs.items():
                        if kw_key in my_class.compulsory_default_kwargs.keys():
                            setattr(self,kw_key,kw_value)
                        else:
                            raise Exception ('Invalid key-word argument passed {}'.format(kw_key))
                #elif((key!='self') & (key!='kwargs') ):
                   # setattr(self,key,value)
            for key , value in my_class.compulsory_default_kwargs.items():
                if key not in kwargs.keys():
                    setattr(self,key,value)


    this_value = 'Foo'    
    my_cl = my_class(3,this_value,p='B',r=10)
    my_cl.__dict__
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.