我有一个伪或特殊属性,可以用三种不同的方式命名(注意:我不控制生成对象的代码)
属性中的值(取决于哪一个设置)完全相同,我需要进行进一步处理,因此根据数据来源,我可以得到类似的内容:
>>> 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'
或
>>> obj.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'a'
>>> obj.b
'value'
>>> obj.c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'c'
或
>>> obj.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'a'
>>> obj.b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'b'
>>> obj.c
'value'
我对获取'value'
感兴趣,遗憾的是__dict__
属性在该对象中不存在。所以我最终为获得该值而做的只是做了一堆getattr
次调用。假设可能性只有三个,代码看起来像这样:
>>> g = lambda o, l: getattr(o, l[0], getattr(o, l[1], getattr(o, l[2], None)))
>>> g(obj, ('a', 'b', 'c'))
'value'
现在,我想知道是否有更好的方法呢?因为我100%确信我做了什么:)
提前致谢
答案 0 :(得分:38)
怎么样:
for name in 'a', 'b', 'c':
try:
thing = getattr(obj, name)
except AttributeError:
pass
else:
break
答案 1 :(得分:2)
这样做的好处是可以使用任意数量的项目:
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)
但我觉得这不是什么大不了的事。即使使用双重查找,生成器表达式也可能比普通的旧循环更快。
答案 2 :(得分:0)
我认为使用dir会让你__dict__
通常做同样的事情......
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
>>>
答案 3 :(得分:0)
根据对象的结构,可能有更好的方法,但不知道其他什么,这里是一个递归解决方案,其工作方式与当前解决方案完全相同,只不过它可以使用任意数量的参数:< / p>
g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None
答案 4 :(得分:-1)
还有一个:
reduce(lambda x, y:x or getattr(obj, y, None), "a b c".split(), None)
(在Python 3中你必须从functools导入reduce。它是Python 2内置的)