The Python Oracle

How can I create an object and add attributes to it?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Sunrise at the Stream

--

Chapters
00:00 How Can I Create An Object And Add Attributes To It?
00:55 Answer 1 Score 477
01:48 Accepted Answer Score 283
02:16 Answer 3 Score 191
02:45 Answer 4 Score 58
02:54 Thank you

--

Full question
https://stackoverflow.com/questions/2827...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #class #object #attributes

#avk47



ANSWER 1

Score 477


The built-in object can be instantiated but can't have any attributes set on it. (I wish it could, for this exact purpose.) This is because it doesn't have a __dict__ to hold the attributes.


I generally just do this:

class Object(object):
    pass

obj = Object()
obj.somefield = "somevalue"

But consider giving the Object class a more meaningful name, depending on what data it holds.


Another possibility is to use a sub-class of dict that allows attribute access to get at the keys:

class AttrDict(dict):
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

obj = AttrDict()
obj.somefield = "somevalue"

To instantiate the object attributes using a dictionary:

d = {"a": 1, "b": 2, "c": 3}

for k, v in d.items():
    setattr(obj, k, v)



ACCEPTED ANSWER

Score 283


You could use my ancient Bunch recipe, but if you don't want to make a "bunch class", a very simple one already exists in Python -- all functions can have arbitrary attributes (including lambda functions). So, the following works:

obj = lambda: None
obj.somefield = 'somevalue'

Whether the loss of clarity compared to the venerable Bunch recipe is OK, is a style decision I will of course leave up to you.




ANSWER 3

Score 191


There is types.SimpleNamespace class in Python 3.3+:

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtuple, typing.NamedTuple could be used for immutable objects. PEP 557 -- Data Classes suggests a mutable alternative.

For a richer functionality, you could try attrs package. See an example usage. pydantic may be worth a look too.




ANSWER 4

Score 58


The mock module is basically made for that.

import mock
obj = mock.Mock()
obj.a = 5