[Python-ideas] Generator/Coroutiine Ontology (was async/await in Python)
Nick Coghlan
ncoghlan at gmail.com
Sat Apr 25 06:02:24 CEST 2015
On 18 April 2015 at 16:05, Andrew Barnert
<abarnert at yahoo.com.dmarc.invalid> wrote:
> On Apr 17, 2015, at 21:48, Rustom Mody <rustompmody at gmail.com> wrote:
>>
>> On Sat, Apr 18, 2015 at 12:28 AM, Yury Selivanov
>> <yselivanov.ml at gmail.com> wrote:
>>> Hello python-ideas,
>>>
>>> Here's my proposal to add async/await in Python.
>>>
>>> I believe that PEPs 380 and 3156 were a major breakthrough for Python 3,
>>
>> I am also interested in this topic --- from the other side.
>> As a teacher of python it is my finding that the
>> terminology/documentation around generators is rather chaotic and
>> messy.
>> Basically given:
>> def foo():
>> yield 1
>> bar = foo()
>>
>> what do we call foo and what do we call bar?
>> It is suggested that foo is "generator-function" and bar is "generator-object"
>> Unfortunately python does not aid this distinction; witness
>>
>>>>> def foo():
>> ... yield 1
>> ...
>>>>> bar = foo()
>>>>> type(foo)
>> <class 'function'>
>>>>> type(bar)
>> <class 'generator'>
>
> I assume you're ok with the type(bar); the type of a generator object is named "generator", just like the type of a bound method object is named "method" and the type of an integer object is named "int", and so on.
>
> So presumably you don't like the former. But what about it?
>
> The only thing I can imagine is the fact that, even though a generator function is conceptually a "subkind" of function, there is no generator function subtype of the function type?
>
> But so what? There's no closure function subtype, just functions whose closure is nonempty; there's no positive int subtype, just ints whose value is positive; etc. And likewise, there's no callable supertype that function and method (and other things) inherit.
>
> If there were some additional API that a generator function should provide that other functions don't (or some implementation reason that makes it worth subclassing for convenience, I suppose), that would be a good reason for needing a subtype. For example, generator a subtype of iterator, just as file is, because they both add new methods that don't make sense for the base iterator type.
>
> But just wanting repr(type(x)) to give you more information about x, that's not a good reason to add a subtype.
>
> So, it seems to me like both of these are returning something you should reasonably expect.
Catching up on email following PyCon travel, there's a reasonable
question here related to the repr() of "foo" itself:
>>> def foo():
... yield 1
...
>>> foo
<function foo at 0x7f7dad9f7bf8>
>>> import dis
>>> dis.show_code(foo)
Name: foo
Filename: <stdin>
Argument count: 0
Kw-only arguments: 0
Number of locals: 0
Stack size: 1
Flags: OPTIMIZED, NEWLOCALS, GENERATOR, NOFREE
Constants:
0: None
1: 1
Modifying the repr of a function based on whether or not the GENERATOR
flag was set on the code object would be quite doable. For example,
the above could be:
>>> foo
<function foo at 0x7f7dad9f7bf8 (generator)>
type(foo) would still be unchanged, we'd just be exposing some
additional info in the value repr().
While it's a less significant behavioural difference than being a
generator function, a non-empty closure could conceivably also be
reported in the repr():
<function foo at 0x7f7dad9f7bf8 (closure)>
<function foo at 0x7f7dad9f7bf8 (closure,generator)>
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list