seeking deeper (language theory) reason behind Python design choice

Ian Kelly ian.g.kelly at gmail.com
Fri May 11 09:31:01 EDT 2018


On Fri, May 11, 2018 at 1:01 AM, Chris Angelico <rosuav at gmail.com> wrote:
> On Fri, May 11, 2018 at 12:38 PM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
>> Would you also contend that generator functions are wrong because they
>> pretend to be normal functions?
>>
>> def totally_not_a_generator(n):
>>     while True:
>>         if n % 2 == 0:
>>             n //= 2
>>         else:
>>             n = n * 3 + 1
>>         stealthily = n
>>         yield stealthily
>>         if n == 1:
>>             return n
>>
>> py> print(totally_not_a_generator(42))  # Lies!
>> <generator object totally_not_a_generator at 0x77fe4d78c0f8>
>
> Let's see. It's created with 'def'. It can be called by putting
> parentheses after its name. Inside the parentheses, you can give it
> parameters. When called, it returns a value. Hmm. Sure looks like a
> function to me.
>
> Tell me, which of these are functions and which are not?
>
> def tnag5():
>     return totally_not_a_generator(5)
>
> def tnag(n):
>     return iter(totally_not_a_generator(n))
>
> def ILY():
>     return iter([1, 2, 3]) # your heart starts beating
>
> async def what_about_me():
>     await spam()
>     return 42
>
> def digits_to_number(text):
>     return int(text, 10)
>
> class run_command:
>     """Compatibility shim for older API"""
>     def __init__(self, *args):
>         proc = subprocess.run(*args, stdout=subprocess.PIPE)
>         self.rc = proc.returncode
>         self.output = proc.output
>
> def run_command(*args):
>     proc = subprocess.run(*args, stdout=subprocess.PIPE)
>     return {"rc": proc.returncode, "output": proc.output}
>
>
> The only one that inspect.isfunction() returns False for is the class,
> and even that is a very function-like class. Every one of these is
> callable and will return a useful value. Their headers announce one of
> three things:
>
> 1) "I am a function" ==> def name(...):
> 2) "I am a factory for objects of my own type" ==> class name:
> 3) "I am a coroutine function" ==> async def name(...):
>
> Not one of them is lying. And nor is your totally_not_a_generator. As
> Steven said, it's a function, and it returns a value.

It's a generator that says it's not a generator. How is that not lying?

Anyway, as far as I can see you just repeated the same argument that
Steven wrote. I know all this, of course, and I think you missed the
point. Please read my response to Steven.



More information about the Python-list mailing list