Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make class iterable respecting inheritance

Well simply making a class iterable is easy enough using meta classes (so some other answers here). However I wish to make a class iterable, and also enabling one to "iterate a subgroup based on inheritance". An example of my use:

class IterPartRegistry(type):
    def __iter__(cls):
        return iter(cls._registry)


class A(object, metaclass=IterPartRegistry):
    _registry = []
    def __init__(self, name):
        self.name = name
        self._registry.append(self)

class B(A):
    pass

class C(A):
    pass


A("A - first")
B("B - first")
B("B - second")
C("C - first")

for t in A:
    print(t.name)

print(" --- ")
for t in B:
    print(t.name)

exit()

The first loop works - it iterates over all instances and childs of "A". However the second loop should only run over the specific subgroup of "A" - those that are instances of the child "B" (or children further down the line).

(How) can this be achieved easiest? In such a way adding more subclasses require least amount of work/change?

like image 557
paul23 Avatar asked Jan 16 '16 21:01

paul23


1 Answers

You can use isinstance to insure that you are getting only class instances

In your code its a one line change:

class IterPartRegistry(type):
    def __iter__(cls):
        return (c for c in cls._registry if isinstance(c, cls))
like image 194
Yoav Glazner Avatar answered Sep 28 '22 16:09

Yoav Glazner