[Python-ideas] Cofunctions PEP - Revision 4

Nick Coghlan ncoghlan at gmail.com
Wed Aug 11 11:37:35 CEST 2010

On Wed, Aug 11, 2010 at 6:03 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> is evaluated by first checking whether the object ``f`` implements
> a ``__cocall__`` method. If it does, the cocall expression is
> equivalent to
> ::
>    yield from f.__cocall__(*args, **kwds)
> except that the object returned by __cocall__ is expected to be an
> iterator, so the step of calling iter() on it is skipped.

I think I'd like to see this exist for a while as:

    yield from f.cocall(*args, **kwds)

for a while after PEP 380 is implemented before it is given syntactic sugar.

Similar to my other suggestion, a @cofunction decorator could easily
provide a cocall method without implementing __call__.

The compiler wouldn't pick up usages of f.cocall() without yield from
with this approach, but tools like pychecker and pylint could
certainly warn about it.

> If ``f`` does not have a ``__cocall__`` method, or the ``__cocall__``
> method returns ``NotImplemented``, then the cocall expression is
> treated as an ordinary call, and the ``__call__`` method of ``f``
> is invoked.
> Objects which implement __cocall__ are expected to return an object
> obeying the iterator protocol. Cofunctions respond to __cocall__ the
> same way as ordinary generator functions respond to __call__, i.e. by
> returning a generator-iterator.

You want more than the iterator protocol - you want the whole
generator API (i.e. send() and throw() as well as __next__()).

> Certain objects that wrap other callable objects, notably bound methods,
> will be given __cocall__ implementations that delegate to the underlying
> object.

If you use a @cofunction decorator, you can define your own descriptor
semantics, independent of those for ordinary functions.

> The use of a decorator instead of ``codef`` was also suggested, but the
> current
> proposal makes this unnecessary as well.

I'm not sure that is really an advantage, given that using a decorator
gives much greater control over the way cofunctions behave.

> It has been questioned whether some combination of decorators and functions
> could be used instead of a dedicated ``cocall`` syntax. While this might be
> possible, to achieve equivalent error-detecting power it would be necessary
> to write cofunction calls as something like
> ::
>    yield from cocall(f)(args)
> making them even more verbose and inelegant than an unadorned ``yield
> from``.
> It is also not clear whether it is possible to achieve all of the benefits
> of
> the cocall syntax using this kind of approach.

As far as I can see, the only thing dedicated syntax adds is the
ability for the compiler to detect when a cofunction is called without
correctly yielding control. But pylint/pychecker would still be able
to do that with a decorator based approach.

I'd really want to see a nice clean @cofunction decorator approach
based on PEP 380 seriously attempted before we threw our hands up and
said new syntax was the only way.


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list