Search code examples
pythoniterable-unpackingargument-unpacking

Python: can I unpack arguments without calling a function?


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.


Solution

  • 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.