有没有其他方法可以遍历自定义类的属性,但排除内置属性?

11

有没有其他方法只迭代自定义类的属性,而不是内置属性(如__dict____module__等)?例如,在这段代码中:

class Terrain:
    WATER = -1
    GRASS = 0
    HILL = 1
    MOUNTAIN = 2

我可以按照以下方式遍历所有这些属性:
for key, value in Terrain.__dict__.items():
    print("{: <11}".format(key), " --> ", value)

输出结果为:

MOUNTAIN     -->  2
__module__   -->  __main__
WATER        -->  -1
HILL         -->  1
__dict__     -->  <attribute '__dict__' of 'Terrain' objects>
GRASS        -->  0
__weakref__  -->  <attribute '__weakref__' of 'Terrain' objects>
__doc__      -->  None

如果我只想要整数参数 (一个基本版本的枚举类型),我可以使用以下代码:

for key, value in Terrain.__dict__.items():
    if type(value) is int: # type(value) == int
        print("{: <11}".format(key), " --> ", value)

这将得到预期的结果:
MOUNTAIN    -->  2
WATER       -->  -1
HILL        -->  1
GRASS       -->  0

是否有可能独立于类型,仅迭代自定义类的非内置属性,例如,如果属性不全是整数。我可以扩展条件来包括更多类型,但我想知道是否有其他我所错过的方法。


1
你似乎在搜索 flufl.enum - JBernardo
对于像这样的简单脚本,我总是尽可能使用内置模块,但这个模块看起来很有趣。 - Ricardo Altamirano
只需将您的“Terrain”类作为“flufl.enum.Enum”的子类即可完成。 - JBernardo
你是否在定义任何方法或只是属性?如果没有定义方法,可以使用字典替代。 - Nomen Nescio
3个回答

19

我会使用:

for key, value in Terrain.__dict__.items():
    if not key.startswith("__"):
        print(...)

或者我会创建一个实际的枚举类型来实现我的需求。


Terrain.__dict__.items() 不就等同于 vars(Terrain).items() 吗? - DSM
对于一个实际的枚举类型,像这个可能已经足够了,对吧?或者你有什么代码可以使用和推荐吗? - Ricardo Altamirano
你也应该检查 key.endswith - John La Rooy
自然地,对于实例变量,您需要使用 self .. 因此 for key, value in self.__dict__.items(): - FloatingRock

3
您可以尝试像这样做:

您可以尝试像这样做:

class GenericClass(object): pass
class_builtins = set(dir(GenericClass))

terrain_attributes = {attr: getattr(Terrain, attr) for attr in dir(Terrain) if attr not in class_builtins}

1

内置属性应该以“__”开头和结尾,因此:

[(k,v) for k,v in Terrain.__dict__.items() if not (k.startswith('__')
    and k.endswith('__'))]

有些人喜欢创建自己的__attributes__,所以这段代码对他们来说可能无法正常工作。嘿,这个命名空间是保留的,这就是原因。
你还需要检查__slots__

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