Search code examples
pythonpython-attrs

How to get @property methods in asdict?


I have something like:

from attr import attrs, attrib

@attrs
class Foo():
    max_count = attrib()
    @property
    def get_max_plus_one(self):
         return self.max_count + 1

Now when I do:

f = Foo(max_count=2)
f.get_max_plus_one =>3

I want to convert this to dict:

{'max_count':2, 'get_max_plus_one': 3}

When I used attr.asdict(f) I do not get the @property. I get only {'max_count':2}.

What is the cleanest way to achieve the above?


Solution

  • For this case, you can use dir on the object, and get only the properties that do not start with __ i.e. ignore the magic methods:

    In [496]: class Foo():
         ...:     def __init__(self):
         ...:         self.max_count = 2
         ...:     @property
         ...:     def get_max_plus_one(self):
         ...:          return self.max_count + 1
         ...:     
    
    In [497]: f = Foo()
    
    In [498]: {prop: getattr(f, prop) for prop in dir(f) if not prop.startswith('__')}
    Out[498]: {'get_max_plus_one': 3, 'max_count': 2}
    

    To handle the regular methods that do not start with __, you can add a callable test:

    In [521]: class Foo():
         ...:     def __init__(self):
         ...:         self.max_count = 2
         ...:     @property
         ...:     def get_max_plus_one(self):
         ...:          return self.max_count + 1
         ...:     def spam(self):
         ...:         return 10
         ...:     
    
    In [522]: f = Foo()
    
    In [523]: {prop: getattr(f, prop) for prop in dir(f) if not (prop.startswith('__') or callable(getattr(Foo, prop, None)))}
    Out[523]: {'get_max_plus_one': 3, 'max_count': 2}