Home > Software engineering >  Check if Callable object is function
Check if Callable object is function

Time:06-22

Is there a way to distinguish between a built-in function <class 'function'>, and any other callable object that implements __call__ method?

Say we want a function with this definition:

def is_callable_function(obj: Callable) -> bool: ...

and we have these callables:

def function(*args, **kwargs): ...

class CallableObj1:
   def __call__(self, *args, **kwargs): ...

class CallableObj2:
   @classmethod
   def __call__(cls, *args, **kwargs): ...

class CallableObj3:
   @staticmethod
   def __call__(*args, **kwargs): ...

then it works like:

>>> is_callable_function(function)
True
>>> is_callable_function(CallableObj1)
False
>>> is_callable_function(CallableObj2)
False
>>> is_callable_function(CallableObj3)
False

Technically an implementation like this one below will work:

def is_callable_function(obj: Callable) -> bool:
   return type(obj).__name__ == "function"

but I believe that there is a better way.

CodePudding user response:

inspect.isfunction(obj) does what you want.

import inspect

class A:
    def __call__(self, *args, **kwargs):
        ...

def a():
    ...

print(inspect.isfunction(A())) # False
print(inspect.isfunction(a)) # True

doc: https://docs.python.org/3/library/inspect.html#inspect.isfunction

CodePudding user response:

You have several options in Python to detect whether some object is a function or not. The first one and most common is using callable() function but in your case you may be able to solve the problem by using isinstance(yourFunction, types.FunctionType) having imported the types module.

You can also check whether an object has __call__ attribute with hasattr(obj, '__call__'), but I think the previous methods are better in your case.

import types

def function():
    return 0

class CallableObj1:
   def __call__(self, *args, **kwargs):
       pass

class CallableObj2:
   @classmethod
   def __call__(cls, *args, **kwargs):
       pass

class CallableObj3:
   @staticmethod
   def __call__(*args, **kwargs):
       pass
   
#Check if object is function
print(isinstance(function, types.FunctionType))
print(isinstance(CallableObj3, types.FunctionType))

#Check if object is callable
print(callable(function))
print(callable(CallableObj3))

#Check if object has __call__ attribute, equivalent to callable()
print(hasattr(function, '__call__'))
print(hasattr(CallableObj3, '__call__'))

Output:

True
False
True
True
True
True
  • Related