Problem
I want to be able to iterate over a type without instantiating it, similar to an enum.
class Foo:
"""Class I want to iterate over without instantiating."""
ALLOWED_VALUES = (1, 2, 3)
# I want iterating over `Foo` to be equivalent to iterating over `Foo.ALLOWED_VALUES`
for val_from_tuple, val_from_foo in zip(Foo.ALLOWED_VALUES, Foo):
assert val_from_tuple == val_from_foo
This behaviour is possible with an enum, but only if ALLOWED_VALUES are valid python names. I want to have the same iteration behaviour without this restriction.
What I tried
I tried implementing __iter__() as a staticmethod on Foo so that an instance of Foo wouldn't be needed to get an Iterator for it. This allows me to iterate over Foo.__iter__(), but iter(Foo) raises an error. This seems to be because iter(Foo) looks for an __iter__ method on type, not on Foo (since Foo is a type object).
class Foo:
"""Class I want to iterate over without instantiating."""
ALLOWED_VALUES = (1, 2, 3)
@staticmethod
def __iter__():
return Foo.ALLOWED_VALUES
# This works, but isn't what I want because it involves calling `__iter__()` explicitly.
for val in Foo.__iter__():
print(val)
# This raises an error:
# `TypeError: 'type' object is not iterable`
for val in Foo:
print(val)