使对象的属性可迭代

2 投票
4 回答
3209 浏览
提问于 2025-04-16 09:36

我得到了一个包含多个属性的对象列表,像这样:

results = q.fetch(5)
for p in results:
    print "%s %s, %d inches tall" % (p.first_name, p.last_name, p.height

我想知道是否可以遍历这些属性,这样我就可以像这样写 for x in p。我想检查每个属性的值,但我不想写一大堆的IF语句。

4 个回答

1

要获取一个模型类的属性列表,可以调用 Model.properties()(或者 instance.properties() - 这是一个类方法)。这个方法会返回一个字典,字典里把属性名和属性类的实例对应起来;你可以通过 getattr(instance, name) 来获取这些属性的值。

如果你在使用 Expando,还可以用 instance.dynamic_properties(),这个方法会返回一个该对象上动态定义的属性列表。

3

你可以通过创建一个新的类来继承原来的变量类型,并定义你自己的iter(self)函数,这样就能实现你想要的效果。比如说,如果你想改变字典的遍历方式,可以这样做:

>>> class mydict(dict):
...    def __iter__(self):
...      for i in self.items():
...          yield i
... 
>>> x = mydict( {'a' : 1, 'b':2 } )
>>> for i in x:
...   print i
... 
('a', 1)
('b', 2)
6

我建议不要这样做。虽然有些特殊情况可能需要这样做,但大多数时候,避免这种 hack 的解决方案会更好。不过,如果你真的想这么做,可以使用 vars() 来获取一个属性的字典,然后遍历它。正如 @Nick 在下面提到的,App Engine 使用属性而不是直接的值来定义它的成员,所以你需要使用 getattr() 来获取它们的值。

results = q.fetch(5)
for p in results:
    for attribute in vars(p).keys()
        print '%s = %s' % (attribute, str(getattr(p, attribute)))

下面演示了 vars() 的作用:

>>> class A:
...     def __init__(self, a, b):
...         self.a = a
...         self.b = b
... 
>>> a = A(1, 2)
>>> vars(a)
{'a': 1, 'b': 2}
>>> for attribute in vars(a).keys():
...     print '%s = %s' % (attribute, str(getattr(a, attribute)))
... 
a = 1
b = 2

撰写回答