Существуют ли другие способы итерации атрибутов пользовательского класса, исключая встроенные?

Есть ли другой способ перебора только атрибутов пользовательского класса, которые не встроены (например, __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

Если мне просто нужны целые аргументы (a рудиментарная версия перечисленного типа), я могу использовать это:

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

Я бы использовал:

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

Или я бы создал фактический нумерованный тип, который сделал то, что я хотел.

Ответ 2

Вы можете попробовать что-то вроде этого:

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}

Ответ 3

Встроенные атрибуты должны начинаться и заканчиваться на "__", поэтому:

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

Некоторым людям нравится создавать свои собственные __attributes__, чтобы этот код не работал должным образом. Эй, там причина, по которой это пространство имен зарезервировано

Вам также нужно будет проверить __slots__