获取传递给函数的参数的列表/元组/结构?

鉴于以下职能:

def foo(a, b, c):
pass

如何获得传入的参数的列表/tuple/dict/etc,而不用自己动手建造

具体来说,我正在寻找 Python 版本的 JavaScript 的 arguments关键字或 PHP 的 func_get_args()方法。

我正在寻找的是一个使用 *args**kwargs的解决方案; 我需要在函数定义中指定参数名(以确保它们被传入) ,但是在函数中,我想使用列表或 dict 样式的结构来处理它们。

53175 次浏览

You've specified the parameters in the header?

Why don't you simply use that same info in the body?

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

What have I missed?

You can create a list out of them using:

args = [a, b, c]

You can easily create a tuple out of them using:

args = (a, b, c)

You can use locals() to get a dict of the local variables in your function, like this:

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


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

This is a bit hackish, however, as locals() returns all variables in the local scope, not only the arguments passed to the function, so if you don't call it at the very top of the function the result might contain more information than you want:

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}

I would rather construct a dict or list of the variables you need at the top of your function, as suggested in the other answers. It's more explicit and communicates the intent of your code in a more clear way, IMHO.

I would use *args or **kwargs and throw an exception if the arguments are not as expected

If you want to have the same errors than the ones checked by python you can do something like

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]))

using with somethin like

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

You can use the inspect module:

def foo(x):
return x


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

This is a duplicate of this and this.

From the accepted answer from a duplicate (older??) question https://stackoverflow.com/a/582206/1136458 :

    frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
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__

Here's a function you can call to get the kwargs of the current function. Or if you want to use those lines directly in your own function instead of calling get_kwargs() just remove the .f_back

import inspect




def get_kwargs():
frame = inspect.currentframe().f_back
keys, _, _, values = inspect.getargvalues(frame)
kwargs = {}
for key in keys:
if key != 'self':
kwargs[key] = values[key]
return kwargs




def test(x, y=100):
z = 7
print(get_kwargs())




test(5, 6)
# Output: {'x': 5, 'y': 6}
test(5)
# Output: {'x': 5, 'y': 100}