Python: can I unpack arguments without calling a function?

769 views Asked by At

I have dict that I want to convert to several different objects. For instance:

Currently Have

kwargs = {'this': 7, 'that': 'butterfly'}

And I want to convert it, maybe using something similar to function argument unpacking, but without actually calling a function, so that I end up with something like:

Desired

**kwargs
print(this) # Will print out `7`
print(that) # Will print out `'butterfly'`

I know that I cannot use the double-star [**] bare like I have shown. But is there something similar I can do?


Edit: More Specifics

Since folks were asking for details and warning that what I am trying to do is dangerous, I will give more context for my need.

I have a property in a class that I want to set using keyword arguments. Something like what is shown here, but unpacking kwargs instead of args.

As a functioning toy example, it looks like this:


class A(object):
    def __init__(self):
        self._idx = None
    @property
    def idx(self):
        return self._idx
    @idx.setter
    def idx(self, kwargs):
        print(kwargs)
        self._idx = {}
        for kw, val in kwargs.items():
            self._idx[kw] = val

This works. But now I am unit testing the function, and in the unit test, I would like to be able to provide the specific key-value pairs as normal objects, so that I can effectively use hypothesis and pytest's @mark.parametrize effectively.

In order to do this, it looks like I will need the "bare unpacking" like I described above.

Since these are all actually local variables within a method, I feel like @g.d.d.c's concerns are probably not significant. It sounds like his worries were if I created new global variables without knowing what they were.

2

There are 2 answers

2
g.d.d.c On BEST ANSWER

Note: this approach is dangerous. You should not (in most circumstances) muddle with locals() or globals(). However, what you want can be done, kind of:

>>> kwargs = {'this': 7, 'that': 'butterfly'}
>>> 
>>> locals().update(kwargs)
>>> this
7
>>> that
'butterfly'

It still calls a function (the update on locals()) but it does give you names in your local namespace.

1
Natim On

You could do:

this, that = {"this": 7, "that": "butterfly"}.values()

But it is really specific. The question would be why do you have the values in a dict in the first place.

You seem to have them in kwargs, why cannot you expend them there?

If you don't know the keys in the dict how can you then use them in the code?

If you know the keys in the dict, why not simply expand it like so:

this, that = kwargs["this"], kwargs["that"]

And my final question? Why not use kwargs["this"] where you need the variable, especially if you don't need it a lot.

Can you provide us with the real use case so that we can tell you how we would do that?