Python Forum
detecting a generstor passed to a funtion
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
detecting a generstor passed to a funtion
#1
what is the appropriate pythonic way for a function to detect that a generator is passed to it? i can do this:
if type(arg).__name__=='generator':
    print('got a generator')
else:
    print('did not get a generator')
i cannot do:
if isinstance(arg,generator):
    print('got a generator')
else:
    print('did not get a generator')
because generator is not defined.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
look at collections.abc
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
from collections.abc import Generator
from typing import Generator as TypingGenerator
from inspect import isgeneratorfunction, isgenerator


def foo():
    """Function"""

def bar():
    """Generatorfunction"""
    yield


print("foo", isgeneratorfunction(foo))
print("bar", isgeneratorfunction(bar))

print("foo()", isgenerator(foo()))
print("bar()", isgenerator(bar()))

# Generator could not detect a Generatorfunction
# but a Generator

print("bar()", isinstance(bar(), Generator))
print("bar()", isinstance(bar(), TypingGenerator))
I'm not sure about typing.Generator. It detects a generator, but typing is used for type hints, which is used for IDEs and Code Linters. One question, many solutions...
buran likes this post
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#4
(Sep-19-2021, 06:06 AM)DeaD_EyE Wrote: # Generator could not detect a Generatorfunction
Not sure what you mean with this comment. The output is

Output:
foo False bar True foo() False bar() True bar() True bar() True
note, blank lines between output pairs are mine.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
Maybe looking for something like this?

>>> g = (x for x in range(20))
>>> g
<generator object <genexpr> at 0x10d4a6820>
>>> import types
>>> isinstance(g, types.GeneratorType)
True
Reply
#6
(Sep-19-2021, 07:55 AM)buran Wrote: Not sure what you mean with this comment. The output is

from inspect import isgeneratorfunction


def normal_function():
    return None

def generator_function():
    yield


print("Type of normal_function", type(normal_function))
print("Type of generator_function", type(generator_function))
print("How to find out if generator_function is a generator without calling it?")
print("Return-Type of generator_function()", type(generator_function()))
print("Now the detection of a generator_function without calling this function")
print(isgeneratorfunction(generator_function))
Output:
Type of normal_function <class 'function'> Type of generator_function <class 'function'> How to find out if generator_function is a generator without calling it? Return-Type of generator_function() <class 'generator'> Now the detection of a generator_function without calling this function True
A simplified implementation from inspect just for functions, not methods.
(it could also detect generator methods, but the code in inspect is a bit different and does crazy wrapping)
CO_GENERATOR = 32


def isgeneratorfunction(func):
    if hasattr(func, "__code__"):
        return bool(func.__code__.co_flags & CO_GENERATOR)    

    return False
With typing.Generator and with collections.abc.Generator you can't detect if a function will return a generator without calling the function.
You can call the generator and without iterating it or use of the send method, the generator does not execute the code inside.
The thing is, that you call a function to check if it's a Generator and if it's the case, to throw it away or vice versa.
But there is another important point to bring up.

If you have a function which could be a generator, but you don't know it and another fact is, if you call the wrong function, it can take much time to compute something. But what if you have a worker with a bunch of functions/generators/coroutines and you need to branch to put the tasks into the right worker. The synchronous functions to the threaded/multiprocess-worker, the generators to an async worker aswell the coroutines. Calling a generatorfunction, return the generator. Calling a coroutine, returns the coroutine object. Calling a ordinary function, returns the result. But if you want to put this function with arguments to the threaded worker, you can't call the function inside the process which put the tasks to the right workers. So you need to be able to detect this, before you call a function.

The function has in the code-object flags, which define which type the function is.
The Flags:
Output:
CO_OPTIMIZED = 1 CO_NEWLOCALS = 2 CO_VARARGS = 4 CO_VARKEYWORDS = 8 CO_NESTED = 16 CO_GENERATOR = 32 CO_NOFREE = 64 CO_COROUTINE = 128 CO_ITERABLE_COROUTINE = 256 CO_ASYNC_GENERATOR = 512
You should be careful what you ask. The rabbit hole is quite deep.
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#7
(Sep-19-2021, 08:00 AM)bowlofred Wrote: Maybe looking for something like this?

>>> g = (x for x in range(20))
>>> g
<generator object <genexpr> at 0x10d4a6820>
>>> import types
>>> isinstance(g, types.GeneratorType)
True

so, could i do:
from types import GeneratorType as generator
followed by that 2nd failing example of mine?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#8
(Sep-19-2021, 11:08 AM)DeaD_EyE Wrote: You should be careful what you ask. The rabbit hole is quite deep.

i was asking about the kind of generator that can be expressed between the () in a call to a function, but i probably should also be detecting for a callable function that has a yield statement, as determined by the compiler?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#9
(Sep-20-2021, 05:42 PM)Skaperen Wrote: so, could i do:
from types import GeneratorType as generator
followed by that 2nd failing example of mine?

Looks good to me..

from types import GeneratorType as generator

arg = (x for x in range(5))
if isinstance(arg,generator):
    print('got a generator')
else:
    print('did not get a generator')
Output:
got a generator
Skaperen likes this post
Reply
#10
i am happy, now. thanks!
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python BLE Scanner not detecting device alexanderDennisEnviro500 0 321 Aug-01-2021, 02:29 AM
Last Post: alexanderDennisEnviro500
  how to modify a variable that is passed as parameter StefanL38 2 752 Dec-07-2020, 08:39 AM
Last Post: StefanL38
  Detecting power plug Narayan 2 1,156 Aug-01-2020, 04:29 AM
Last Post: bowlofred
  Detecting USB Device Insertion on Windows 10 Atalanttore 0 877 Jan-17-2020, 02:46 PM
Last Post: Atalanttore
  are numeric types passed by value or reference? rudihammad 4 1,031 Nov-19-2019, 06:25 AM
Last Post: rudihammad
  Detecting windows shutdown event riccardoob 4 2,327 Nov-12-2019, 04:51 PM
Last Post: Aurthor_King_of_the_Brittons
  Detecting String Elements in a List within Given Message Redicebergz 6 1,846 Mar-19-2019, 03:12 PM
Last Post: buran
  Detecting if image matches another kainev 2 1,536 Dec-02-2018, 02:00 PM
Last Post: kainev
  Detecting file extensions ellipsis 1 1,273 Nov-15-2018, 07:44 AM
Last Post: buran
  Is there a way to append to a list WITHOUT modifying the parameter passed? arnavb 11 3,109 Sep-23-2018, 07:16 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020