Make class iterative respect for inheritance

Well, just making the iterable class easy enough using meta classes (so some other answers here). However, I want to make the class iterable, and also allow "sort through the 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 children of "A". However, the second cycle should work only on a specific subgroup "A" - those that are instances of the child "B" (or children further down the line).

(How) can this be achieved easiest? So adding more subclasses requires less work / change?

+5
source share
2 answers

You can use isinstance to ensure that you only get instances of the class

In your code, its one line change:

 class IterPartRegistry(type): def __iter__(cls): return (c for c in cls._registry if isinstance(c, cls)) 
+3
source

You can let each class maintain its own list of instances by providing each with its own _registry class _registry . Then, instead of checking if each instance has a specific class, you can instead _registry over all the values ​​in _registry for each subclass of cls . To find these subclasses, you can use the cls.__subclasses__() method:

 import itertools as IT class IterPartRegistry(type): def __init__(cls, name, bases, attrs): super(IterPartRegistry, cls).__init__(name, bases, attrs) cls._registry = [] def __iter__(cls): yield from cls._registry for subcls in cls.__subclasses__(): yield from subcls class A(object, metaclass=IterPartRegistry): def __init__(self, name): self.name = name self._registry.append(self) class B(A): pass class C(A): pass class D(B, C): pass A("A - first") B("B - first") B("B - second") C("C - first") D("D - first") for t in A: print(t.name) print(" --- ") for t in B: print(t.name) 

gives

 A - first B - first B - second D - first C - first D - first --- B - first B - second D - first 
+2
source

Source: https://habr.com/ru/post/1240774/


All Articles