How to get @property methods in asdict?

风格不统一 提交于 2020-12-09 06:55:12

问题


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?


回答1:


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}



回答2:


In general, you would have to iterate over the classes attributes and check for instances of property and then call the properties __get__ method using the instance. So, something like:

In [16]: class A:
    ...:     @property
    ...:     def x(self):
    ...:         return 42
    ...:     @property
    ...:     def y(self):
    ...:         return 'foo'
    ...:

In [17]: a = A()

In [18]: vars(a)
Out[18]: {}

In [19]: a.x
Out[19]: 42

In [20]: a.y
Out[20]: 'foo'

In [21]: {n:p.__get__(a) for n, p in vars(A).items() if isinstance(p, property)}
Out[21]: {'x': 42, 'y': 'foo'}



回答3:


I’m afraid that isn’t supported by attrs at the moment. You may want to follow/comment on https://github.com/python-attrs/attrs/issues/353 which may give you what you want eventually.



来源:https://stackoverflow.com/questions/51733882/how-to-get-property-methods-in-asdict

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!