11

Is there another way to iterate through only the attributes of a custom class that are not in-built (e.g. __dict__, __module__, etc.)? For example, in this code:

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

I can iterate through all of these attributes like this:

for key, value in Terrain.__dict__.items():
    print("{: <11}".format(key), " --> ", value)

which outputs:

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

If I just want the integer arguments (a rudimentary version of an enumerated type), I can use this:

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

this gives the expected result:

MOUNTAIN    -->  2
WATER       -->  -1
HILL        -->  1
GRASS       -->  0

Is it possible to iterate through only the non-in-built attributes of a custom class independent of type, e.g. if the attributes are not all integral. Presumably I could expand the conditional to include more types, but I want to know if there are other ways I'm missing.

Community
  • 1
  • 1
Ricardo Altamirano
  • 14,650
  • 21
  • 72
  • 105

3 Answers3

19

I would use:

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

Or I would create an actual enumerated type that did what I wanted.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
3

You could try something like this:

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}
Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
1

Builtin attributes should start and end with '__' so:

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

Some people like to create their own __attributes__ so this code wouldn't work properly for them. Hey there's a reason why this namespace is reserved

You'll also have to check for __slots__

John La Rooy
  • 295,403
  • 53
  • 369
  • 502