通过getattr动态获取字典元素?
我想动态地查询我想从一个类中获取哪些对象。getattr 这个函数看起来正是我需要的,它在获取类中的顶层对象时效果很好。不过,我还想指定一些子元素。
class MyObj(object):
def __init__(self):
self.d = {'a':1, 'b':2}
self.c = 3
myobj = MyObj()
val = getattr(myobj, "c")
print val # Correctly prints 3
val = getattr(myobj, "d['a']") # Seemingly incorrectly formatted query
print val # Throws an AttributeError
我该如何通过字符串来获取对象的字典元素呢?
4 个回答
2
如果你想让字典里的项目也是动态的,那你需要在调用 getattr
的结果上再使用 get
方法:
value = getattr(myobj, 'd').get('a')
3
你只需要用方括号就可以获取字典里的元素:
val = getattr(myobj, "d")["a"]
这样就会把 val
设置为 1
。
9
你遇到错误的原因是因为 getattr(myobj, "d['a']")
在找一个叫 d['a']
的属性,但这个属性并不存在。你的属性叫 d
,它是一个字典。只有在你拿到这个字典的引用后,才能访问里面的内容。
mydict = getattr(myobj, "d")
val = mydict["a"]
或者像其他人展示的那样,你可以一步到位(我分成两步是为了更清楚地说明实际发生了什么):
val = getattr(myobj, "d")["a"]
你的问题暗示你认为对象里的字典项是对象的“子元素”。其实,字典里的项和对象的属性是两回事。(getattr()
也不能用在像 o.a
这样的东西上;它只是获取一个对象的一个属性。如果那个属性也是一个对象,而你想获取它的某个属性,那就要用另一个 getattr()
。)
你可以很容易写一个函数,按照给定的字符串路径逐步查找属性,并尝试将每个名称解析为字典的键或对象的属性:
def resolve(obj, attrspec):
for attr in attrspec.split("."):
try:
obj = obj[attr]
except (TypeError, KeyError):
obj = getattr(obj, attr)
return obj
这里的基本思路是,你拿一个路径,然后对路径中的每个部分,尝试在字典类型的容器中找到一个项,或者在对象上找到一个属性。当你走到路径的尽头时,就返回你找到的内容。你的例子可以是 resolve(myobj, "d.a")
。