How to define a default list of attributes for instances of a class?

I think Hugh Bothwell is on the right track, but it can be done more concisely:

class MyClass(object):
    _defaults = "attr1", "attr2", "attr3"
    _default_value = None

    def __init__(self, **kwargs):
        self.__dict__.update(dict.fromkeys(self._defaults, self._default_value))
        self.__dict__.update(kwargs)


my_object = MyClass(attr3='overridden', attr4='added')

print(vars(my_object))

Output:

{'attr4': 'added', 'attr2': None, 'attr3': 'overridden', 'attr1': None}

I made _defaults and _default_value class attributes (which could be changed at runtime). (Providing a mutable default value would likely require additional code to prevent it from being shared by every instance created, however.)

This would be easy to extend to allow defining different (immutable) default values for each default attribute:

class MyClass(object):
    _defaults = {
        "attr1": None,
        "attr2": 0,
        "attr3": ""
    }

    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults)
        self.__dict__.update(kwargs)


my_object = MyClass(attr3='overridden', attr4='added')

print(vars(my_object))

Output:

{'attr4': 'added', 'attr2': 0, 'attr3': 'overridden', 'attr1': None}

Like this?

class MyObject(object):
    def __init__(self, attr1 = default1, attr2 = default2):
        self.attr1 = attr1
        self.attr2 = attr2

You can instantiate a MyObject with or without specifying the attributes

myObject1 = MyObject() # gets default values 
myObject2 = MyObject(foo, bar) # overrides defaults

You could also use keyword arguments (kwargs) if you have a variable number of attributes, see here for examples.


If you have many properties to be passed, it may be more readable this way:

class Myclass(object):
    def __init__(self, **kwargs):
        defaults = {
            "attr1": None,
            "attr2": 0,
            "attr3": ""
        }
        defaults.update(kwargs)
        for attr,value in defaults.iteritems():
            self.__setattr__(attr, value)

Edit: looking at @martineau and @kosii's suggestions, here is another possibility:

class MyClass(object):
    defaults = {
        "attr1": None,
        "attr2": 0,
        "attr3": ""
    }

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __getattr__(self, key):
        try:
            # return a default value
            return MyClass.defaults[key]
        except KeyError:
            raise AttributeError("don't recognize .{}".format(key))

... in this case, recognized object attributes return default values if they have not actually been set yet.