seeking deeper (language theory) reason behind Python design choice

Chris Angelico rosuav at gmail.com
Fri May 11 03:01:57 EDT 2018


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. That's not
materially different from ILY() in my example - it returns something
which you can iterate over.

ChrisA



More information about the Python-list mailing list