如何在 asdict 中获取 @属性 方法?
How to get @property methods in asdict?
我有类似的东西:
from attr import attrs, attrib
@attrs
class Foo():
max_count = attrib()
@property
def get_max_plus_one(self):
return self.max_count + 1
现在当我这样做时:
f = Foo(max_count=2)
f.get_max_plus_one =>3
我想将其转换为字典:
{'max_count':2, 'get_max_plus_one': 3}
当我使用 attr.asdict(f)
时,我没有得到 @property
。我只得到
{'max_count':2}
.
实现上述目标最干净的方法是什么?
对于这种情况,您可以在对象上使用 dir
,并且只获取不以 __
开头的属性,即忽略魔术方法:
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}
要处理不以 __
开头的常规方法,您可以添加一个 callable
测试:
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}
通常,您必须遍历 类 属性并检查 property
的实例,然后调用属性 __get__
方法使用实例。所以,像这样:
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'}
恐怕 attrs
目前不支持。你可能想在 https://github.com/python-attrs/attrs/issues/353 上 follow/comment,这最终可能会给你想要的东西。
如果定义:
import attr
def attr2dict(inst):
dic = attr.asdict(inst)
dic.update({n: p.__get__(inst) for n, p in vars(type(inst)).items() if isinstance(p, property)})
return dic
然后你就会得到你要找的东西:
>>> attr2dict(f)
{'max_count': 2, 'get_max_plus_one': 3}
我有类似的东西:
from attr import attrs, attrib
@attrs
class Foo():
max_count = attrib()
@property
def get_max_plus_one(self):
return self.max_count + 1
现在当我这样做时:
f = Foo(max_count=2)
f.get_max_plus_one =>3
我想将其转换为字典:
{'max_count':2, 'get_max_plus_one': 3}
当我使用 attr.asdict(f)
时,我没有得到 @property
。我只得到
{'max_count':2}
.
实现上述目标最干净的方法是什么?
对于这种情况,您可以在对象上使用 dir
,并且只获取不以 __
开头的属性,即忽略魔术方法:
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}
要处理不以 __
开头的常规方法,您可以添加一个 callable
测试:
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}
通常,您必须遍历 类 属性并检查 property
的实例,然后调用属性 __get__
方法使用实例。所以,像这样:
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'}
恐怕 attrs
目前不支持。你可能想在 https://github.com/python-attrs/attrs/issues/353 上 follow/comment,这最终可能会给你想要的东西。
如果定义:
import attr
def attr2dict(inst):
dic = attr.asdict(inst)
dic.update({n: p.__get__(inst) for n, p in vars(type(inst)).items() if isinstance(p, property)})
return dic
然后你就会得到你要找的东西:
>>> attr2dict(f)
{'max_count': 2, 'get_max_plus_one': 3}