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