Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Object with @property's to dict

I'm new to Python so please excuse if I've glazed over something simple to do this.

I have an object like this:

class myObject(object):
    def __init__(self):
        self.attr1 = None
        self.attr2 = None

    @property
    def prop1(self):
        return foo.some_func(self.attr1)

And I instantiate it like this:

a = myObject()
a.attr1 = 'Apple'
a.attr2 = 'Banana'

And the method it's all wrapped in expects a return of dict, so I do this:

return a.__dict__

but prop1 is not included in the return. I understand why this is, it's not in the object's __dict__ because it only holds real attributes.

So the question is, how can I make my return, return something like this:

{'attr1': 'Apple', 'attr2': 'Banana', 'prop1': 'ModifiedApple'}

other than right before the return doing:

a.prop1_1 = a.prop1
like image 415
Skinner927 Avatar asked Jan 08 '23 15:01

Skinner927


2 Answers

You should leave __dict__ be, only use it for attributes that live directly on the instance.

If you need to produce a dictionary with attribute names and values that includes the property, you could just add another property or method that produces a new dicitonary:

@property
def all_attributes(self):
    return dict(vars(self), prop1=self.prop1)

This could be automated with introspection to detect all property objects, but take into account that you use properties to avoid having to do the calculation up-front in the first place; triggering calculations for all properties may not be all that desirable.

like image 66
Martijn Pieters Avatar answered Jan 17 '23 22:01

Martijn Pieters


What you want is the inspect module.

a = myObject()
a.attr1 = 'Apple'
a.attr2 = 'Banana'
inspect.getmembers(a)

returns

[('attr1','Apple'),('attr2','Banana'),('prop1','ModifiedApple')...]

Note that getmembers will also return builtin members like __sizeof__, so you may need to apply a bit of filtering to the list.

If you want it as a dictionary you can always use

dict(inspect.getmembers(a))
like image 41
Nick Bailey Avatar answered Jan 17 '23 23:01

Nick Bailey