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
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.
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
  How to receive two passed cmdline parameters and access them inside a Python script? pstein 2 279 Feb-17-2024, 12:29 PM
Last Post: deanhystad
  iterating and detecting the last Skaperen 3 1,029 Oct-01-2022, 05:23 AM
Last Post: Gribouillis
  Detecting float or int in a string Clunk_Head 15 4,283 May-26-2022, 11:39 PM
Last Post: Pedroski55
  module detecting if imported vs not Skaperen 1 1,637 Nov-19-2021, 07:43 AM
Last Post: Yoriz
  Python BLE Scanner not detecting device alexanderDennisEnviro500 0 1,973 Aug-01-2021, 02:29 AM
Last Post: alexanderDennisEnviro500
  how to modify a variable that is passed as parameter StefanL38 2 2,075 Dec-07-2020, 08:39 AM
Last Post: StefanL38
  Detecting power plug Narayan 2 2,673 Aug-01-2020, 04:29 AM
Last Post: bowlofred
  Detecting USB Device Insertion on Windows 10 Atalanttore 0 2,341 Jan-17-2020, 02:46 PM
Last Post: Atalanttore
  are numeric types passed by value or reference? rudihammad 4 2,575 Nov-19-2019, 06:25 AM
Last Post: rudihammad
  Detecting windows shutdown event riccardoob 4 5,626 Nov-12-2019, 04:51 PM
Last Post: Aurthor_King_of_the_Brittons

Forum Jump:

User Panel Messages

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