Stefan Rank
1/22/2008 3:30:00 PM
on 22.01.2008 16:09 Paul McGuire said the following:
> On Jan 22, 7:46 am, Stefan Rank <list-e...@strank.info> wrote:
>> I also need to test for generator functions from time to time for which
>> I use::
>>
>> def _isaGeneratorFunction(func):
>> '''Check the bitmask of `func` for the magic generator flag.'''
>> return bool(func.func_code.co_flags & CO_GENERATOR)
>>
>> cheers,
>> stefan
>
> Might want to catch AttributeError in this routine - not all func
> arguments will have a func_code attribute. See below:
>
> class Z(object):
> def __call__(*args):
> for i in range(3):
> yield 1
>
> for i in Z()():
> print i
> # prints 1 three times
>
> import types
> print type(Z()()) == types.GeneratorType
> # prints 'True'
>
> print Z()().func_code
> # raises AttributeError, doesn't have a func_code attribute
You are right about that for generator *objects*.
But _isaGeneratorFunction tests for generator *functions* (the ones you
call in order to get a generator object) and those must have a func_code.
So in your example::
>>> from compiler.consts import CO_GENERATOR
>>> Z().__call__.func_code.co_flags & CO_GENERATOR
32
>>> Z.__call__.func_code.co_flags & CO_GENERATOR
32
You have to use __call__ directly, you can't use the code-object-flag
test on the callable class instance Z(), but I think that's just as well
since this kind of test should not be necessary at all, except in rare
code parts (such as Diez' microthreading experiments).
cheers,
stefan