getting dynamic attribute in python
本问题已经有最佳答案,请猛点这里访问。
我有一个和对象,它有一个伪属性或特殊属性,可以用三种不同的方式命名(注意:我不控制生成对象的代码)
属性中的值(取决于设置了哪一个)完全相同,我需要获取该值进行进一步处理,因此根据数据源,我可以具有如下内容:
1 2 3 4 5 6 7 8 9 10 | >>> 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' |
或
1 2 3 4 5 6 7 8 9 10 | >>> 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' |
号
或
1 2 3 4 5 6 7 8 9 10 | >>> 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' |
我对获取
1 2 3 | >>> g = lambda o, l: getattr(o, l[0], getattr(o, l[1], getattr(o, l[2], None))) >>> g(obj, ('a', 'b', 'c')) 'value' |
。
现在,我想知道有没有更好的方法?因为我100%确信我所做的一切:)
提前谢谢
怎么样:
1 2 3 4 5 6 7 | for name in 'a', 'b', 'c': try: thing = getattr(obj, name) except AttributeError: pass else: break |
这有助于处理任意数量的项目:
1 2 3 | def getfirstattr(obj, *attrs): return next((getattr(obj, attr) for attr in attrs if hasattr(obj, attr)), None) |
。
这确实有一个非常小的缺点,即它对最终值进行两次查找:一次检查属性是否存在,另一次实际获取值。这可以通过使用嵌套的生成器表达式来避免:
1 2 3 | def getfirstattr(obj, *attrs): return next((val for val in (getattr(obj, attr, None) for attr in attrs) if val is not None), None) |
但我觉得这没什么大不了的。生成器表达式可能会比普通的旧循环更快,即使使用双重查找也是如此。
根据对象的结构,可能有更好的方法来实现这一点,但是不知道其他什么,这里有一个递归解决方案,它的工作方式与当前的解决方案完全相同,只是它将使用任意数量的参数:
1 | g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None |
。
我认为使用dir基本上可以得到和
1 2 3 4 | targetValue ="value" for k in dir(obj): if getattr(obj,k) == targetValue: print"%s=%s"%(k,targetValue) |
有点像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> 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 >>> |
号
另一个是:
1 | reduce(lambda x, y:x or getattr(obj, y, None), "a b c".split(), None) |
。
(在python 3中,必须从functools导入reduce。它是Python2中内置的)