Python optional, positional and keyword arguments

2019-07-27 06:14发布

问题:

This is a class I have:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

The idea is to encapsulate a dictionary and add some functionality with a special keyword. The dictionary can still hold do_something though you can't add it at creation time. For all other aspects it behaves just like a normal dictionary.

Anyway, the problem is that whatever I give to args it starts by assigning the first value to do_something which is not what I want.

What I do now is this:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if not isinstance(do_something, bool):
            args = list(args)
            args.append(do_something)
        elif do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

But it doesn't look right to me. I could also check for the do_something value in kwargs, but it will be worse, since I mess with the signature removing useful information...

Is there any way in python to use optional, positional and keyword arguments safely? If not are there other simpler workarounds?

I'm on python 2.6

回答1:

It's new in Python 3. The best workaround in Python 2 is

def foo(*args, **kwargs):
    do_something = kwargs.pop("do_something", False)

The behaviour you see happens because Python tries to be clever in matching up arguments, so for instance it will make a keyword argument positional if you pass too many positional arguments.

PS why not store it as an attribute of metadict instead of as an entry in the dict?