I'd like to make a dictionary subclass that takes in positional keywords in addition to the standard *args, **kwargs. I found this example on stackoverflow:

class attrdict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.__dict__ = self

a = attrdict(x=1, y=2)
print a.x, a.y
print a['x']
b.x, b.y  = 1, 2
print b.x, b.y

I'd like to know how to modfiy it to take in a positional argument. Something like:

class attrdict(dict):
    def __init__(self,positional, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.positional=positional

### This doesn't
a = attrdict(50, 30, 20)
>>>TypeError: dict expected at most 1 arguments, got 2

This doesn't seem to want to accept multiple args. I was able to rectify this by overwriting the update method, something like:

def update(self, *args, **kwargs):
    'do stuff'

However, it seems like whenever I define the update module, I lose the ability to define the instance variable, self.positional.

For example, if I do:

### Without overwriting update()
a
>>>{}
a.positional
>>>50


### With overwriting update()
a
>>>  #No dictionary!
a.positional
>>> 50

Has anyone ever succesffuly made a custom dict that takes *args, and a positional argument?

You can add a positional argument but your code must conform the rules to call the dict() function. For example this doesn't work

>>> dict(20, 30)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: dict expected at most 1 arguments, got 2

Here is what the python documentation says about dict():

Return a new dictionary initialized from an optional positional argument or from a set of keyword arguments. If no arguments are given, return a new empty dictionary. If the positional argument arg is a mapping object, return a dictionary mapping the same keys to the same values as does the mapping object. Otherwise the positional argument must be a sequence, a container that supports iteration, or an iterator object. The elements of the argument must each also be of one of those kinds, and each must in turn contain exactly two objects. The first is used as a key in the new dictionary, and the second as the key’s value. If a given key is seen more than once, the last value associated with it is retained in the new dictionary.

In first approximation, this means that the *args must contain at most one argument which can be a dict or a sequence of pairs (key, value).

Edited 4 Years Ago by Gribouillis

Thanks Griboulis. Sorry to make you copy that for me, but after programming all day, my mind is shot so that helps a lot just to have someone point me back on the path of sanity.

It seems like, then, to get the behavior I want, I do want to overwrite the update method rather than doing something like:

self.__dict__ = self 

Which will map instance variables that I want to keep separate right into my dictionary. I will drop *args and just use **kwargs. The only appealing thing about *args is that I could send items into my dictionary and have keys auto-generate based on some combination of attributes. In reality, this is probably more harmful than good, as it requires an object in my dictionary to have a method to do this, so I will avoid it.

This article has been dead for over six months. Start a new discussion instead.