Newbie question: How do I add elements to **kwargs in a function?

A

Aaron Garrett

I have spent quite a bit of time trying to find the answer on this
group, but I've been unsuccessful. Here is what I'd like to be able to
do:

def A(**kwargs):
kwargs['eggs'] = 1

def B(**kwargs):
print(kwargs)

def C(**kwargs):
A(**kwargs)
B(**kwargs)

I'd like to be able to make a call like:

C(spam=0)

and have it print
{'spam': 0, 'eggs': 1}

But it doesn't do that. Instead, it gives
{'spam': 0}

I was under the impression that kwargs is passed by reference and,
since I'm only modifying it (rather than making it point to something
else) that the changes would be reflected back out to the thing being
passed in.

So, why doesn't this work the way I expect it to? And, is there some
other way to make this work to accomplish the same goal?

Thank you in advance,
Aaron
 
C

Chris Rebert

I have spent quite a bit of time trying to find the answer on this
group, but I've been unsuccessful. Here is what I'd like to be able to
do:

def A(**kwargs):
   kwargs['eggs'] = 1

def B(**kwargs):
   print(kwargs)

def C(**kwargs):
   A(**kwargs)
   B(**kwargs)

I'd like to be able to make a call like:

C(spam=0)

and have it print
{'spam': 0, 'eggs': 1}

But it doesn't do that. Instead, it gives
{'spam': 0}

I was under the impression that kwargs is passed by reference and,

It's not. Semantically, the dictionary broken up into individual
keyword arguments on the calling side, and then on the callee side, a
fresh dictionary is created from the individual arguments. So while
Python uses call-by-object, extra packing/unpacking takes place in
this case, causing copying, and thus your problem.

Cheers,
Chris
 
A

Aaron Garrett

I have spent quite a bit of time trying to find the answer on this
group, but I've been unsuccessful. Here is what I'd like to be able to
do:
def A(**kwargs):
   kwargs['eggs'] = 1
def B(**kwargs):
   print(kwargs)
def C(**kwargs):
   A(**kwargs)
   B(**kwargs)
I'd like to be able to make a call like:

and have it print
{'spam': 0, 'eggs': 1}
But it doesn't do that. Instead, it gives
{'spam': 0}
I was under the impression that kwargs is passed by reference and,

It's not. Semantically, the dictionary broken up into individual
keyword arguments on the calling side, and then on the callee side, a
fresh dictionary is created from the individual arguments. So while
Python uses call-by-object, extra packing/unpacking takes place in
this case, causing copying, and thus your problem.

Cheers,
Chris


Thank you for the explanation.

Aaron
 
G

Gabriel Genellina

En Tue, 17 Mar 2009 01:24:18 -0200, Aaron Garrett
I have spent quite a bit of time trying to find the answer on this
group, but I've been unsuccessful. Here is what I'd like to be able to
do:
def A(**kwargs):
   kwargs['eggs'] = 1
def B(**kwargs):
   print(kwargs)
def C(**kwargs):
   A(**kwargs)
   B(**kwargs)
I'd like to be able to make a call like:

and have it print
{'spam': 0, 'eggs': 1}
But it doesn't do that. Instead, it gives
{'spam': 0}
I was under the impression that kwargs is passed by reference and,

It's not. Semantically, the dictionary broken up into individual
keyword arguments on the calling side, and then on the callee side, a
fresh dictionary is created from the individual arguments. So while
Python uses call-by-object, extra packing/unpacking takes place in
this case, causing copying, and thus your problem.

Thank you for the explanation.

There is still a way of getting what you want -- you must pass the actual
dictionary, and not unpack/repack the arguments:

def A(kwargs): # no **
kwargs['eggs'] = 1

def B(**kwargs):
print(kwargs)

def C(**kwargs):
A(kwargs) # no **
B(**kwargs)

C(spam=0)
 

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
474,294
Messages
2,571,511
Members
48,202
Latest member
ClaudioVil

Latest Threads

Top