在Python中循环遍历一个类的所有成员变量

137

如何获取一个可迭代的类中所有变量的列表?就像locals()一样,但是针对类

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

    def as_list(self)
       ret = []
       for field in XXX:
           if getattr(self, field):
               ret.append(field)
       return ",".join(ret)
这应该会返回
>>> e = Example()
>>> e.as_list()
bool143, bool2, foo

为什么不能使用 for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ] 呢?怎么会不知道类的实例变量呢? - S.Lott
4
S.Lott最终还是采用了这种方式。在我的实际代码中,我有大约40个变量,我认为最好的做法是不必手动创建迭代列表,这样做更加简洁。 - priestc
3
可能是Python中遍历对象属性的重复问题 - Trevor Boyd Smith
8个回答

209
dir(obj)

提供对象的所有属性。需要自己过滤出成员和方法等信息:

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

example = Example()
members = [attr for attr in dir(example) if not callable(getattr(example, attr)) and not attr.startswith("__")]
print members   

将会给你:

['blah', 'bool143', 'bool2', 'foo', 'foobar2000']

14
为什么要实例化一个对象:dir(Example()),而不是只使用类类型 dir(Example)? - Erdal
9
你是如何获取这些值的? - knutole
8
getattr(object, attr) 的意思是获取对象 object 中名为 attr 的属性。 - opello
8
callable(attr)如何工作?attr不是一个字符串吗? - cubuspl42
8
如果您想检查一个对象是否可调用,那么您应该使用vars(Example).items()或者vars(instance.__class__).items()而不是dir(),因为dir()只会返回字符串作为名称。 - rrw
显示剩余5条评论

158

如果您只想使用变量(而不是函数),请使用:

vars(your_object)

5
你仍需要过滤__vars__,但这就是正确的答案。 - gaborous
3
我很喜欢这种方法,打算用它来找出在发送状态之前要进行序列化的内容,例如在网络上传输。 - Thom
19
vars不包括类变量,只包括实例变量。 - DilithiumMatrix
2
@DilithiumMatrix,你需要在类本身上使用vars(THECLASSITSELF)来获取类变量。请查看我下面的回答。 - Amir Hossein Baghernezad
2
使用以下方法来特别回答OP的问题:members = list(vars(example).keys()),因为(至少在Python3中)vars返回一个将成员变量的名称映射到其值的dict - Michael Hall
显示剩余3条评论

33

@truppo:您的答案几乎是正确的,但 callable 总是会返回 false,因为您只是传递了一个字符串。您需要像以下这样的内容:

[attr for attr in dir(obj()) if not callable(getattr(obj(),attr)) and not attr.startswith("__")]

这将过滤掉函数


ClassName.dict["doc"] 这将过滤掉函数、内置变量等,只提供您需要的字段! - Hyuga Hinata

7
>>> a = Example()
>>> dir(a)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', 'bool143', 'bool2', 'blah',
'foo', 'foobar2000', 'as_list']

正如您所见,这给出了所有属性,因此您需要进行一些过滤。但基本上,dir()是您要寻找的。


ClassName.dict["doc"] 这将过滤掉函数、内置变量等,只提供您需要的字段! - Hyuga Hinata

2

类似于vars(),可以使用以下代码列出所有类属性。它等同于vars(example).keys()

example.__dict__.keys()

1
ClassName.dict["doc"] 这将过滤掉函数、内置变量等,只提供您需要的字段! - Hyuga Hinata

-1
ClassName.__dict__["__doc__"]

这将过滤掉函数、内置变量等内容,并仅返回您需要的字段!

1
你确定它确实打印出空的吗!!! - Max

-1
row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns} if r else {}

使用这个。


误导性。默认情况下,类中没有属性'table'。 - ben26941
ClassName.dict["doc"] 这将过滤掉函数、内置变量等,只提供您需要的字段! - Hyuga Hinata

-4

做这件事的简单方法是将该类的所有实例保存在一个列表中。

a = Example()
b = Example()
all_examples = [ a, b ]

对象不会自发地出现。你的程序的某个部分是有目的地创建它们的。创建是有原因的。将它们收集到列表中也可能有原因。

如果你使用工厂,你可以做到这一点。

class ExampleFactory( object ):
    def __init__( self ):
        self.all_examples= []
    def __call__( self, *args, **kw ):
        e = Example( *args, **kw )
        self.all_examples.append( e )
        return e
    def all( self ):
        return all_examples

makeExample= ExampleFactory()
a = makeExample()
b = makeExample()
for i in makeExample.all():
    print i

我喜欢这个想法(我可能会在当前项目中使用它)。但这并不是问题的答案:原帖作者想要列出属性,而不是实例本身。 - balpha
@balpha:哎呀。没有仔细看问题。90%的情况下,这是一个“如何找到类的所有实例”的重复问题。现在你指出来了,实际问题并不合理。你知道实例变量,只需制作一个列表即可。 - S.Lott
ClassName.__dict__["__doc__"]这会过滤掉函数、内置变量等,只提供你所需的字段! - Hyuga Hinata

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接