Is it possible get a dictionary of passed in parameters similar to kwargs(python)?
我正在创建一个这样的对象:
1 2 3 4 5 | class Obj(object): def __init__(self,**kwargs): params = ['val1','val2','val3','val4',...] for p in params: setattr(self,p,kwargs.get(p,None)) |
我这样做所以我不必这样做:
1 2 3 4 5 6 7 | class Obj(object): def __init__(self,val1=None,val2=None,val3=None,val4=None,...): self.val1=val1 self.val2=val2 self.val3=val3 self.val4=val4 ... |
我的问题是,你能混合两种吗? 我可以在哪里定义预期的参数但仍然循环参数来设置属性? 我喜欢定义预期参数的想法,因为它是自我记录的,而其他开发人员不必搜索使用的kwargs。
我知道这看起来很小,但是我正在用一些XML创建一个对象,所以我将传递许多参数,它只会使代码混乱并且让我烦恼。
我确实谷歌这个,但找不到任何东西,可能是因为字典和kwargs一起指向kwarg的例子。
更新:更具体地说,是否有可能获得传入参数的字典,所以我根本不需要使用kwargs?
Sudo代码:
1 2 3 4 | class Obj(object): def __init__(self,val1=None,val2=None,val3=None,val4=None,...): for k,v in dictionary_of_paramters.iteritems(): setattr(self,k,v) |
您可以使用
1 2 3 4 | import inspect def myargs(val1, val2, val3=None, val4=5): print inspect.currentframe().f_locals |
它显示当前堆栈帧上可用的所有本地。
1 2 | myargs('a','b') ==> {'val3': None, 'val2': 'b', 'val1': 'a', 'val4': 5} |
(注意:不保证在所有Python解释器上实现)
编辑:我同意这不是一个漂亮的解决方案。我会做的更像是:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def _yourargs(*names): "returns a dict with your named local vars" alllocs = inspect.stack()[1][0].f_locals return {n:alllocs[n] for n in names} def askformine(val1, val2, val3=None, val4=5): "example to show just those args i'm interested in" print _yourargs('val1','val2','val3','val4') class Obj(object): "example inserting some named args as instance attributes" def __init__(self, arg1, arg2=4): self.__dict__.update(_yourargs('arg1','arg2')) |
edit2略胜一筹:
1 2 3 4 5 6 7 8 | def pickdict(d,*names): "picks some values from a dict" return {n:d[n] for n in names} class Obj(object): "example inserting some named args as instance attributes" def __init__(self, arg1, arg2=4): self.__dict__.update(pickdict(locals(),'arg1','arg2')) |
如果要在方法的最顶部获取args dict,在定义任何本地之前,这很简单:
1 2 3 | class Obj(object): def __init__(self,val1=None,val2=None,val3=None,val4=None): kwargs = dict(locals()) |
要在以后阅读这个词典,需要一些内省魔法:
1 2 3 4 5 6 7 8 | class Obj(object): def __init__(self,val1=None,val2=None,val3=None,val4=None): # feel free to add more locals loc = dict(locals()) fun = sys._getframe().f_code kwargs = {x:loc[x] for x in fun.co_varnames[:fun.co_argcount]} |
您还可以通过添加如下函数使后者可重用:
1 2 3 | def getargs(): f = sys._getframe(1) return {x:f.f_locals[x] for x in f.f_code.co_varnames[:f.f_code.co_argcount]} |
然后:
1 2 3 4 5 6 | class Obj(object): def __init__(self,val1=None,val2=None,val3=None,val4=None): # feel free to add more locals kwargs = getargs() |
我想这是cpython特有的。
虽然你不能在不使用kwargs或inspect模块的情况下获取参数(参见其他答案),但你可以这样做......
1 2 3 | class Obj(object): def __init__(self, **kwargs): self.__dict__.update(**kwargs) |
每个对象都有一个存储所有属性的字典,您可以通过
关于此方法的一些讨论,请参阅此问题。
没有很好的方法来获取函数的所有参数的字典。
一种丑陋的解决方法:将额外的参数注入kwargs并在想要遍历所有关键字参数的地方使用它(PS这是inspect模块的示例用法,但不建议用于生产用途):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/usr/bin/env python import inspect def inject_defaults(func): """ injects '__defaults' key into into kwargs, so it can be merged with kwargs in the decorated method""" args, varargs, varkwargs, defaults = inspect.getargspec(func) have_defaults = args[-len(defaults):] defaults_dict = dict(zip(have_defaults, defaults)) def fun(*args, **kwargs): kwargs['__defaults'] = defaults_dict return func(*args, **kwargs) return fun @inject_defaults def f1(a,b,c, x=1, **kwargs): kwargs.update(kwargs['__defaults']) del kwargs['__defaults'] for k, v in kwargs.items(): # here, x, y and z will appear print(k, v) f1(1, 2, 3, y=3, z=2) # prints # ('y', 3) # ('x', 1) # ('z', 2) |
是的,你可以混合两者。
见下文:
1 2 | def method(a, b=1, *args, **kwargs): '''some code''' |
这是有效的。这里:
1 2 3 4 | 'a' is a required argument 'b' is a default argument 'args' will have all the non-keyword arguments and 'kwargs' will have all the keyword arguments. |
例:
1 | method(1,2,3,4,5,test=6,test1=7) |
这个电话会有:
1 2 3 4 | a=1 b=2 args=(3,4,5) kwargs={'test':6,'test1':7} |