In the case of itertools.repeat
(and most iterators), using a suitable class that implements the iterator
protocol has several advantages from POV implementation / maintenance - for example, you can better control iteration, you can specialize the class, etc. I also suspect that there are some optimizations that can be done at C level for the right iterators that don't apply to generators.
Also remember that classes and functions are also objects - the def
statement is basically syntactic sugar for creating an instance of function
and fills it with compiled code, local namespace, cells, closure and whatnot (somehow the FWIW task involved, I just did it from because of curiosity, and it was a big PITA), and the class
operator is also syntactic sugar for creating a new instance of type
(doing it manually, in fact, is really trivial). From this, POV yield
is a syntax-like sugar that turns your function into a returned factory instance of a typical generator
builtin type - IOW, which forces your function to act as a class, without the hassle, but also without the fine controls and possible optimizations you can get. by writing a full-blown class.
In a more general left, sometimes when writing your โfunctionโ as a custom called type, instead, similar wins are offered - subtle control, possible optimizations, and sometimes just improved readability (think of two-story decorators, custom descriptors, etc.).
Finally, wrt / builtin types ( int
, str
, etc.) IIRC (please someone correct me if I'm wrong), they were originally functions that acted as factory functions (before the revolution of new-style classes when building types and custom types are different types of objects). Of course, it now makes sense to have them as simple classes, but they should have supported the all_lower naming scheme for compatibility.