在python中获取动态属性

在python中获取动态属性,python,getattr,Python,Getattr,我有一个带有伪属性或特殊属性的and对象,该属性可以用三种不同的方式命名(注意:我不控制生成该对象的代码) 属性中的值(取决于设置的属性)完全相同,我需要获取该值以进行进一步处理,因此根据数据源的不同,我可以得到如下结果: >>> obj.a 'value' >>> obj.b Traceback (most recent call last): File "<stdin>", line 1, in <module> Attribu

我有一个带有伪属性或特殊属性的and对象,该属性可以用三种不同的方式命名(注意:我不控制生成该对象的代码)

属性中的值(取决于设置的属性)完全相同,我需要获取该值以进行进一步处理,因此根据数据源的不同,我可以得到如下结果:

>>> obj.a
'value'
>>> obj.b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'b'
>>> obj.c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'c'
现在,我想知道是否有更好的方法?因为我100%相信我所做的:)


提前感谢

我认为使用dir将得到与通常相同的东西

targetValue = "value"
for k in dir(obj):
    if getattr(obj,k) == targetValue:
       print "%s=%s"%(k,targetValue)
差不多

>>> class x:
...    a = "value"
...
>>> dir(x)
['__doc__', '__module__', 'a']
>>> X = x()
>>> dir(X)
['__doc__', '__module__', 'a']
>>> for k in dir(X):
...     if getattr(X,k) == "value":
...        print "%s=%s"%(k,getattr(X,k))
...
a=value
>>>
那么:

for name in 'a', 'b', 'c':
    try:
        thing = getattr(obj, name)
    except AttributeError:
        pass
    else:
        break

这样做的优点是可以处理任意数量的项目:

 def getfirstattr(obj, *attrs):
     return next((getattr(obj, attr) for attr in attrs 
                  if hasattr(obj, attr)), None)
这确实有一个非常小的缺点,即它对最终值进行两次查找:一次是检查属性是否存在,另一次是实际获取值。使用嵌套的生成器表达式可以避免这种情况:

 def getfirstattr(obj, *attrs):
     return next((val for val in (getattr(obj, attr, None) for attr in attrs)
                  if val is not None), None)

但我真的觉得没什么大不了的。即使使用双重查找,生成器表达式也可能比普通的旧循环快。

根据对象的结构,可能有更好的方法来实现这一点,但不知道其他方法,这是一个递归解决方案,其工作原理与当前解决方案完全相同,只是它可以处理任意数量的参数:

g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None
还有一个:

reduce(lambda x, y:x or  getattr(obj, y, None),  "a b c".split(), None)

(在Python3中,您必须从functools中导入reduce。它是Python2中的一个内置项)

我几乎发布了一些类似的内容。问题是,您最后检查了两次所需的元素(一次使用
hasattr
,一次使用
getattr
)。最后,我认为它并不比WIM发布的显式循环更好,尽管我很乐意听到任何关于循环的优点。我想,您可以使用嵌套的生成器来避免双查找,但是它只在发现属性时发生,所以我认为这是一个小缺点。不过,我刚刚添加了这样一个版本。很好的一个…我要看一看..谢谢检查-没有
get\u value()
(或类似)或者正如您提到的
,这取决于数据源
-没有现有的(或可派生的映射)关于source->attribute name?我实际上是想在这个例子中避免try/except。我应该提到:)try/except是典型的python方式,有什么好的理由你想避免它吗?没有什么好的理由,我只是想保持代码简洁,我觉得尝试/例外有点过分:)我现在检查的另一件事是,如果这些属性都不存在,块不会提供默认值,尽管这是极不可能的,尽管如此,我仍然认为使用防御方法总是好的:)如果您需要的话,可以使用for循环的
else
语句来实现这一点。至于风格问题,python中通常会出现许多try/excepts-请看,我不知道如何将
else
一起用于
for
循环:)谢谢您的支持谢谢这一点,我完全错过了dir()…现在只是想知道dir()调用在内部是如何工作的。假设
bool(obj.b)
为真,我将对此进行检查。如果你有<代码> Obj.a=0 < /代码>,考虑这里会发生什么。我不认为你会接受这个。我真的很喜欢这个,因为简单和简洁
 def getfirstattr(obj, *attrs):
     return next((val for val in (getattr(obj, attr, None) for attr in attrs)
                  if val is not None), None)
g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None
reduce(lambda x, y:x or  getattr(obj, y, None),  "a b c".split(), None)