Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a few objects in my program that have about 10-15 attributes each. These attributes are set at various places in the code in various stages in the program. As it is absolutely fine to set them on the objects without having them defined in the class in Python, there's no good authoritative list in my program of which attributes are used.

I'd like something like the following:

class MyObject(object):
    attr1
    attr2

I've looked at the property() built-in, but it's at least 6 lines of code per property. Is there an easy way to define a list of default attributes without initializing them in Python?

UPDATE: I forgot to mention, most of the values don't have sensible defaults and would effectively be equal to None before used.

like image 803
Adam Lindberg Avatar asked Jun 07 '12 12:06

Adam Lindberg


People also ask

How do you list all attributes and methods of a class or instance?

Method 1: To get the list of all the attributes, methods along with some inherited magic methods of a class, we use a built-in called dir() . Method 2: Another way of finding a list of attributes is by using the module inspect .

How do you define class attributes?

Class attributes are attributes which are owned by the class itself. They will be shared by all the instances of the class. Therefore they have the same value for every instance. We define class attributes outside all the methods, usually they are placed at the top, right below the class header.

What are class instance attributes?

Instance attributes are what we've seen before. These are the attributes that are independent to each object, like the door color or the height, in the previous example. In this example, our Dog class has two instance attributes: . name and .

Where are instance attributes defined?

Instance attributes are defined in the constructor. Defined directly inside a class. Defined inside a constructor using the self parameter. Shared across all objects.


2 Answers

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 image 193
martineau Avatar answered Nov 05 '22 06:11

martineau


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.

like image 37
Junuxx Avatar answered Nov 05 '22 07:11

Junuxx