How do I say "Is this a function"?

John Machin sjmachin at lexicon.net
Sat Apr 26 21:08:25 EDT 2008


Dan Bishop wrote:
> On Apr 26, 6:17 pm, John Henry <john106he... at hotmail.com> wrote:
>> How do I determine is something a function?
>>
>> For instance, I don't want to relying on exceptions below:

And why not?

>>
>> def f1():
>>    print "In f1"
>>
>> def f3():
>>    print "In f3"
>>
>> def others():
>>    print "In others"
>>
>> for i in xrange(1,3):
>>    fct = "f%d()"%(i+1)
>>    try:
>>       exec fct
>>    except:
>>       others()
>>
>> I wish to say:
>>
>>    if value of fct is a funtion, invoke it, otherwise invoke others().
>>
>> Thanks,
> 
> hasattr(fct, '__call__')
> 
> And be careful about using the exec statement.

1. In the OP's code, fct is a string, e.g. "f2()", so hasattr(fct, 
'__call__') will never return True.

2. Objects other than functions have a __call__ attribute. Some callable 
  objects don't have a __call__ attribute.

3. Use __doubleunderscore__ things only when you need them and only when 
you know what you are doing. There are high-level built-in functions 
such as callable and isinstance that can be used for such tests. The 
literal answer to the OP's question is:

from types import FunctionType
if isinstance(fct, FunctionType):
    do_something()

Something like the following will do the required trick (find callables 
in the global namespace whose name matches a pattern) without using the 
dreaded exec. Note I've left out the logic to call others; the OP's code 
will call others once for each missing function ... let's leave him to 
sort out whether that's a good idea or that should be changed to calling 
it only once if all functions are missing.

 >>> def f1():
...    print "in f1"
...
 >>> def f3():
...    print "in f3"
...
 >>> globdict = globals()
 >>> globdict # output prettied manually
{'f1': <function f1 at 0x00BA0470>,
  'f3': <function f3 at 0x00BA04F0>,
  '__builtins__': <module '__builtin__' (built-in)>,
  '__name__': '__main__',
  '__doc__': None}
 >>> for i in xrange(1, 4): ### upper bound 3 probably a bug
...     fname = "f%d" % i
...     if fname in globdict:
...         func = globdict[fname]
...         if callable(func):
...             func()
...
in f1
in f3
 >>>

Cheers,
John



More information about the Python-list mailing list