通过getattr动态获取字典元素?

6 投票
4 回答
9115 浏览
提问于 2025-04-17 12:08

我想动态地查询我想从一个类中获取哪些对象。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")

撰写回答