On Thu, Jan 23, 2014 at 7:43 PM, Steven D'Aprano <st...@pearwood.info> wrote:
> Generators are a kind of function, which are special. You can't inherit
> from them:

I clarified my sloppy language in a reply. `__iter__` should be a
generator function, not a generator. A generator function uses `yield`
and `yield from` expressions, and returns a `generator` when called.
In CPython, the code for a generator function is flagged as
CO_GENERATOR:

    def genfun():
        yield 1

    flags = genfun.__code__.co_flags

    >>> inspect.CO_GENERATOR
    32
    >>> flags & inspect.CO_GENERATOR
    32

But that's CPython specific; use the inspect API instead (2.6+):

    >>> inspect.isgeneratorfunction(genfun)
    True

A "generator expression" also creates a generator. In CPython, this is
implemented by calling an anonymous generator function that gets
instantiated and called automagically.

When a function is called, the interpreter creates a frame to evaluate
the function's bytecode, given the function's globals and the current
thread state. It combines the call's positional and keyword arguments
with the `__defaults__` tuple and `__kwdefaults__` dict to set the
parameters as local variables in the frame. For a closure, it also
loads the free-variable `cell` objects from the `__closure__` tuple.
Everything is ready to call PyEval_EvalFrameEx to evaluate the
frame...

Except if the code is flagged as CO_GENERATOR that doesn't happen.
Instead the interpreter creates and returns a `generator` that
references the frame as its `gi_frame` attribute. Calling the
generator's `__next__` method in turn evaluates the frame up to a
`yield` or `yield from` expression. `StopIteration` is raised when the
frame executes a `return` statement or explicit `return None` -- or
implicitly returns from the last line of the function.

Like the function type, the generator type is finalized (i.e. doesn't
allow subclassing). It's clear why that would be the case for the type
of a singleton object such as None, Ellipsis, NotImplemented, and
True/False (bool). In other cases, supporting subclassing would be
more work (initial coding, bugs, maintenance -- who's volunteering?)
for little gain. For example: slice and range. Other types are so
closely linked to the language that I don't see why anyone would care
to subclass them, such as function, method, generator, frame, code,
and cell [1]. There's a fuzzy line there; property, classmethod, and
staticmethod aren't finalized.

[1] Listing every finalized type in CPython would be tedious. Here's a
few more, if anyone cares: builtin_function_or_method,
method_descriptor, classmethod_descriptor, member_descriptor,
getset_descriptor, wrapper_descriptor, and method-wrapper.
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to