On Fri, May 11, 2018 at 12:38 PM, Ian Kelly <ian.g.ke...@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 -- https://mail.python.org/mailman/listinfo/python-list