generator testing and attrs

M

Mike

I need to be able to store a list of schedulable items, either regular
callables or generator-producing functions -- is there a way to test if a fn
is generator-producing? (In the non-generator case, the fn is a 'tick' fn
that I will call to produce results - a pre-generator implementation.)
I can test for a generator itself with isinstance(f, types.GeneratorType),
but I'm interested in the fn that produces it. For example:

if isGeneratorFn(f):
f = f()
f.next() ...
else:
f()...

If not, I guess it's fairly easy to specify a fn attr like so:
def myGen(): yield foo
myGen.isGenerator = True

but this is not as easy for instance methods, it seems. (No?)
(BTW, +1 from me for PEPs with syntax that let you specify attrs for fn's
and methods in-line with the def'n for cases like this, 'staticmethod', &c.
No reason that c# should win on this one...)

I would call f() the first time and see if the result is a generator object,
but unfortunately in my case returning a generator is possible valid 'data'
(to be scheduled later) and doesn't mean I should call .next() straight
away.

Ideas?
thanks
 
T

Terry Reedy

Mike said:
I need to be able to store a list of schedulable items, either regular
callables or generator-producing functions -- is there a way to test if a fn
is generator-producing?

Yes, but I forget how. The ref-man section on type hierarchy lists
and explains 'special attributes' for each type. Functions or code
objects have an indication of normal vs. generator.

TJR
 
M

Miki Tebeka

Hello Mike,
I need to be able to store a list of schedulable items, either regular
callables or generator-producing functions -- is there a way to test if a fn
is generator-producing? if you do
dir(g)
You'll see that g has many attributes that f doesnt. Maybe you can use one of them.
if isGeneratorFn(f):
f = f()
f.next() ...
else:
f()...
IMO a better way is letting the caller passing you ONLY functions.
In case of a generator if should pass the .next of the generator.
e.g.
l = []
def add_func(f):
l.append(f)

def add_gen(g):
l.append(g().next)

for f in l:
print f()

HTH.
Miki
 
M

Mike

Miki Tebeka said:
You'll see that g has many attributes that f doesnt. Maybe you can use one
of them.

Hmm - doesn't seem so here:
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__',
'__getattribute__', '__hash__', '__init__', '__module__', '__name__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict',
'func_doc', 'func_globals', 'func_name']['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__',
'__getattribute__', '__hash__', '__init__', '__module__', '__name__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict',
'func_doc', 'func_globals', 'func_name']
IMO a better way is letting the caller passing you ONLY functions.
In case of a generator if should pass the .next of the generator.
...code...

As I said, I can't do that becuase I'm saving the items to be scheduled
(evaluated lazily) -- I don't want to call f() or f.next() right right away.
(The code sample could have included the comment "# much later..." between
getting the funarg and calling it.)

Ahh -- Looks like the original PEP (255) held the key:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top