How to get all named args in a dict?

K

kj

Suppose I have the following:

def foo(x=None, y=None, z=None):
d = {"x": x, "y": y, "z": z}
return bar(d)

I.e. foo takes a whole bunch of named arguments and ends up calling
a function bar that takes a single dictionary as argument, and this
dictionary has the same keys as in foo's signature, so to speak.

Is there some builtin variable that would be the same as the variable
d, and would thus obviate the need to explicitly bind d?

Thanks!

kynn
 
C

Chris Rebert

Suppose I have the following:

def foo(x=None, y=None, z=None):
   d = {"x": x, "y": y, "z": z}
   return bar(d)

I.e. foo takes a whole bunch of named arguments and ends up calling
a function bar that takes a single dictionary as argument, and this
dictionary has the same keys as in foo's signature, so to speak.

Is there some builtin variable that would be the same as the variable
d, and would thus obviate the need to explicitly bind d?

def foo(**kwargs):
return bar(kwargs)

I would suggest you read the Python tutorial.

Cheers,
Chris
 
T

Terry Reedy

kj said:
Suppose I have the following:

def foo(x=None, y=None, z=None):
d = {"x": x, "y": y, "z": z}
return bar(d)

I.e. foo takes a whole bunch of named arguments and ends up calling
a function bar that takes a single dictionary as argument, and this
dictionary has the same keys as in foo's signature, so to speak.

Is there some builtin variable that would be the same as the variable
d, and would thus obviate the need to explicitly bind d?

Use the built-in function locals()
x=locals()
print(x)
{'a': 1, 'b': 2}
 
D

Dave Angel

kj said:
That's *exactly* what I was looking for. Thanks!

kynn
You already had a better answer from Chris Rebert:

def foo(**kwargs):
return bar(kwargs)

kwargs at this point is exactly a dictionary of the named arguments to foo.

Because if you try to do anything in this function, you'll probably be
adding more local variables. And then they'd be passed to bar as well.
 
K

kj

You already had a better answer from Chris Rebert:
def foo(**kwargs):
return bar(kwargs)
kwargs at this point is exactly a dictionary of the named arguments to foo.

I disagree. If I defined foo as you show above, then there is no
error checking on the named parameters passed to foo; anything
goes.
Because if you try to do anything in this function, you'll probably be
adding more local variables. And then they'd be passed to bar as well.

That problem is easily solved: just make "x = locals()" the first
statement in the definition of foo.

kynn
 
J

Jason Tackaberry

That problem is easily solved: just make "x = locals()" the first
statement in the definition of foo.

That doesn't solve the problem. You'd need locals().copy()

Cheers,
Jason.
 
J

John Machin

That doesn't solve the problem.  You'd need locals().copy()

Dave's solution doesn't formally solve the problem because x is the
first arg of foo and re-binding x to locals() is not a good idea if
you need to use the passed-in args before calling bar().

Adding .copy() is necessary only if for some weird reason you want to
call locals() *again* before calling bar().

| >>> def foo(x=None, y=None, z=None):
| ... d = locals()
| ... print d
| ... p = 100
| ... print d
| ... print locals()
| ... print d
| ...
| >>> foo(1,2,3)
| {'y': 2, 'x': 1, 'z': 3}
| {'y': 2, 'x': 1, 'z': 3}
| {'y': 2, 'x': 1, 'z': 3, 'd': {...}, 'p': 100}
| {'y': 2, 'x': 1, 'z': 3, 'd': {...}, 'p': 100}
| >>>

Bonus: not only a side-effect, but a recursive one.

Like the manual says, _*UPDATE*_ and return a dictionary ...

HTH,
John
 
D

Dave Angel

kj said:
I disagree. If I defined foo as you show above, then there is no
error checking on the named parameters passed to foo; anything
goes.



That problem is easily solved: just make "x = locals()" the first
statement in the definition of foo.

kynn
Well, you caught me by surprise. The name and number of locals is
determined at compile time, not at run time. But when I run an
experiment, it seems you're right, that the dict changes as the function
executes.

In Python 2.62 at least, the following function gives the following results:

def myfunc(x, y):
print locals()
s = 42
print locals()

myfunc(y=12, x=33)

{'y': 12, 'x': 33}
{'y': 12, 'x': 33, 's': 42, 'r': {'y': 12, 'x': 33}}
{'y': 12, 'x': 33}


So, if one wanted to call bar, but not till after one had defined new
locals, you could do the following:

def foo(x=None, y=None, z=None):
args = locals().copy()
a = new stuff
dosomestuff with a, and maybe y
bar(args)

A shallow copy would be adequate in this case.

Thanks for the correction.
 
J

John Machin

Well, you caught me by surprise.  The name and number of locals is
determined at compile time, not at run time.  But when I run an
experiment, it seems you're right, that the dict changes as the function
executes.

So don't call it again!
In Python 2.62 at least, the following function gives the following results:

def myfunc(x, y):
    print  locals()
    s = 42
    print locals()

myfunc(y=12, x=33)

{'y': 12, 'x': 33}
{'y': 12, 'x': 33, 's': 42, 'r': {'y': 12, 'x': 33}}
{'y': 12, 'x': 33}

So, if one wanted to call bar, but not till after one had defined new
locals, you could do the following:

def foo(x=None, y=None, z=None):
     args = locals().copy()
     a = new stuff
     dosomestuff with a, and maybe y
     bar(args)

A shallow copy would be adequate in this case.

As I (thought I had) demonstrated, *NO* copy would be adequate in that
case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,145
Latest member
web3PRAgeency
Top