如何在 asdict 中获取@property 方法?
Posted
技术标签:
【中文标题】如何在 asdict 中获取@property 方法?【英文标题】:How to get @property methods in asdict? 【发布时间】:2019-01-14 23:06:46 【问题描述】:我有类似的东西:
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
.
实现上述目标的最简洁方法是什么?
【问题讨论】:
【参考方案1】:对于这种情况,您可以在对象上使用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
【讨论】:
Foo
中的所有方法,以及Foo
的 MRO 中的所有方法呢?但是getattr
这里肯定更合适。
@juanpa.arrivillaga 这很快就会变得棘手,我喜欢你的通用方法,但我的解决方案有点具体。
好吧,我的意思很简单,如果Foo
有任何方法,比如Foo.doStuff
,你最终会得到一堆绑定方法。
@juanpa.arrivillaga 够公平的。已编辑。
两个 sn-ps 产生相同的结果 — 那么添加 callable
测试有什么意义呢?【参考方案2】:
通常,您必须遍历 classes 属性并检查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'
【讨论】:
【参考方案3】:恐怕attrs
目前不支持。您可能想关注/评论https://github.com/python-attrs/attrs/issues/353,这可能最终会为您提供您想要的。
【讨论】:
【参考方案4】:如果你定义:
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
【讨论】:
以上是关于如何在 asdict 中获取@property 方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中获取 PSObject.Properties 的 ScriptProperty 值?
如何在C#中获取PSObject.Properties的ScriptProperty值?