我想动态查询我想要检索的类中的哪些对象。 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
如何通过字符串获取对象的字典元素?
答案 0 :(得分:7)
您收到错误的原因是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")
答案 1 :(得分:3)
您只需使用方括号来获取字典的元素:
val = getattr(myobj, "d")["a"]
将val
设置为1
。
答案 2 :(得分:1)
如果您需要字典项也是动态的,则需要在get
的结果上调用getattr
:
value = getattr(myobj, 'd').get('a')
答案 3 :(得分:1)
感谢Kindall的回答,我发现以下内容适用于叮咬的词典。
class Obj2(object):
def __init__(self):
self.d = {'a':'A', 'b':'B', 'c': {'three': 3, 'twothree': (2,3)}}
self.c = 4
class MyObj(object):
def __init__(self):
self.d = {'a':1, 'b':2, 'c': {'two': 2, 'onetwo': (1,2)}}
self.c = 3
self.obj2 = Obj2()
def resolve(self, obj, attrspec):
attrssplit = attrspec.split(".")
attr = attrssplit[0]
try:
obj = obj[attr]
except (TypeError, KeyError):
obj = getattr(obj, attr)
if len(attrssplit) > 1:
attrspec = attrspec.partition(".")[2] # right part of the string.
return self.resolve(obj, attrspec) # Recurse
return obj
def __getattr__(self, name):
return self.resolve(self, name)
# Test
myobj = MyObj()
print getattr(myobj, "c")
print getattr(myobj, "d.a")
print getattr(myobj, "d.c.two")
print getattr(myobj, "obj2.d.a")
print getattr(myobj, "obj2.d.c.twothree")