开发者

Python: Convert args to dict, like PHP's compact?

I want a function exactly like PHP's compact function.

i.e., if I pass in a list of variable names:

compact('var1','开发者_StackOverflow社区var2')

it returns me back a dict:

{'var1':var1, 'var2':var2}


The variable name used in the caller is not easily available to the called function. It's probably possible to do with an advanced use of inspect, but it might be better to rethink why you want the variable names.

UPDATE: Now that I know what your real need is ("I want to pass my variables to my template"), the answer is simple: use locals(): it returns a dictionary mapping all your local variable names to their values.

UPDATE 2: How about this?:

def only(d, *keys):
    """Return the subset of dict `d` whose keys are in `keys`."""
    return dict((k,v) for k,v in d.iteritems() if k in keys)

...

a = 17
b = 23
template_data = only(locals(), "a", "b")


The function does not see the names (if any!-) of its actual arguments -- nor in fact any indication whatsoever that those actual arguments are the results of expressions that happen to be single variables rather than constants, function calls, or other expressions of any kind whatsoever.

So, what you require, as you have specified it, is simply not feasible.


With the help of Getting method parameter names in python, here you go with decorator solution, so that you are able to apply it to any function:

def compactor(func):
    import inspect
    def compactor_impl(*args, **kwargs):
        arg_names = inspect.getargspec(func)[0]
        return dict(zip(arg_names, args))
    return compactor_impl

@compactor
def package(var1, var2, var3):
    pass

@compactor
def package2(var1, var2, var3, supervar):
    pass

assert package(1, 2, 3) == {'var1': 1, 'var2': 2, 'var3': 3,}
assert package2(1, 2, 3, 'boh') == {'var1': 1, 'var2': 2, 'var3': 3, 'var3': 3, 'supervar': 'boh'}

I assumed that the functions do nothing else but return the name-value pairs. You might want to add some checks (asserts) to ensure that len(args) == len(arg_names) and that kwargs is empty, because this will not be checked once the decorator is applied.


>>> import inspect
>>> def compact(*args):
...     d = {}
...     for a in args:
...         d[a] = inspect.stack()[1][0].f_locals[a]
...     return d
...
>>> def test():
...     x = 5
...     print compact('x')
...
>>> test()
{'x': 5}


(1) Python is not PHP. (2) "variable name lost when passed into a function" is true.

Do Not Use Variables for this.

Do something simpler. Use the dict function.

>>> dict( var1=1, var2='a', var3=1+3j )
{'var1': 1, 'var3': (1+3j), 'var2': 'a'}

That seems to do what you want. The variable "names" are in there exactly once. You don't really need to create other local, temporary variables.


if you have a list called args and you want to put it into a dictionary called kwargs as in your example:

for k,v in enumerate(args):
    kwargs["var%d"%(k+1)] = v

the keys are literally the index of the items in args, though; this can't be useful?


This is awkward and has limits, but for the rest it works

def p(*args):
  p = {}
  for i in args:   
     exec 'p["%s"] = %s' % (i, i)
  return p


Just use locals() at the beginning of the function.

def foo(x,y): 
   print x,y

def jar(x,y):
   foo(**locals())

def varjar(x,y):
   print locals()
   args =  locals().copy()
   args['x'] += 1
   args['y'] += 2
   foo(**args)
  • foo(1,2) and jar(1,2) print 1 2
  • varjar(1,2) prints {'y':2,'x':1} and 2 4
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜