Ah, Peter, if only I could achieve your understanding and mastery! On Mon, Apr 17, 2017 at 3:37 AM, Peter Otten <__pete...@web.de> wrote:
> Perhaps it becomes clearer if we build our own class discovery / method > runner system. Given T as the baseclass for classes that provide foo_...() > methods that we want to run, and M as the mix-in that provides such methods > but isn't itself a subclass of T... > [snip] > As you can see, to the discovery algorithm it doesn't matter where the > method is defined, it suffices that it's part of the class and can be found > by dir() or vars(). > [snip] > > $ cat discovery6.py > class T: > pass > > class M: > def foo_one(self): > print(self.__class__.__name__, "one") > def foo_two(self): > print(self.__class__.__name__, "two") > > class X(T): > def foo_x(self): > print(self.__class__.__name__, "x") > > class Y(M, T): > pass > > def safe_issubclass(S, B): > try: > return issubclass(S, B) > except TypeError: > return False > > def discover_Ts(): > for C in globals().values(): > if safe_issubclass(C, T) and C is not T: > print("found", C, "with foo_... methods") > for name in dir(C): > if name.startswith("foo_"): > yield C, name So your discover function does not need to instantiate any objects; it just searches the module's global namespace for class names. Cool! And dir(C) gives all attributes of C including _inherited_ attributes! This clarifies so much. Many thanks, Peter! > def run_method(cls, methodname): > inst = cls() > method = getattr(inst, methodname) > method() > > def main(): > for cls, methodname in discover_Ts(): > run_method(cls, methodname) > > if __name__ == "__main__": > main() > $ python3 discovery6.py > found <class '__main__.Y'> with foo_... methods > Y one > Y two > found <class '__main__.X'> with foo_... methods > X x > > That was easy. We have replicated something similar to the unit test > framework with very little code. > > Now you can go and find the equivalent parts in the unittest source code :) But not tonight ~(:>)) -- boB _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor