How to Detect Whether a Python Variable Is a Function

How do I detect whether a Python variable is a function?

If this is for Python 2.x or for Python 3.2+, you can use callable(). It used to be deprecated, but is now undeprecated, so you can use it again. You can read the discussion here: http://bugs.python.org/issue10518. You can do this with:

callable(obj)

If this is for Python 3.x but before 3.2, check if the object has a __call__ attribute. You can do this with:

hasattr(obj, '__call__')

The oft-suggested types.FunctionTypes or inspect.isfunction approach (both do the exact same thing) comes with a number of caveats. It returns False for non-Python functions. Most builtin functions, for example, are implemented in C and not Python, so they return False:

>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True

so types.FunctionType might give you surprising results. The proper way to check properties of duck-typed objects is to ask them if they quack, not to see if they fit in a duck-sized container.

How to determine if the variable is a function in Python?

The callable built-in mentioned in other answers doesn't answer your question as posed, because it also returns True, besides functions, for methods, classes, instances of classes which define a __call__ method. If your question's title and text are wrong, and you don't care if something is in fact a function but only if it's callable, then use that builtin. But the best answer to your question as posed is: import the inspect method of Python's standard library, and use inspect.isfunction. (There are other, lower-abstraction ways, but it's always a good idea to use functionality of the inspect module for introspection when it's there, in preference to lower-level approaches: inspect helps keep your code concise, clear, robust, and future-proof).

How to check for a function type in Python?

Don't check types, check actions. You don't actually care if it's a function (it might be a class instance with a __call__ method, for example) - you just care if it can be called. So use callable(f).

python 3: how to check if an object is a function?

in python2:

callable(fn)

in python3:

isinstance(fn, collections.Callable)

as Callable is an Abstract Base Class, this is equivalent to:

hasattr(fn, '__call__')

Checking if a Python function referenced anything out-of-scope

You can use inspect.getclosurevars:

Get the mapping of external name references in a Python function or
method func to their current values. A named tuple
ClosureVars(nonlocals, globals, builtins, unbound) is returned.
nonlocals maps referenced names to lexical closure variables, globals
to the function’s module globals and builtins to the builtins visible
from the function body. unbound is the set of names referenced in the
function that could not be resolved at all given the current module
globals and builtins.

Let's see what it returns for your examples:

Case 1:

def foo1(x):
return y + x # yes - it has referenced 'y' which is out of foo1 scope

inspect.getclosurevars(foo1)
# ClosureVars(nonlocals={}, globals={'y': 1}, builtins={}, unbound=set())

Here it detected you are using variable in the global scope.

Case 2:

import colorsys
def foo2(x):
return colorsys.rgb_to_hsv(*x) # yes - it has referenced 'colorsys' which is out of foo2 scope

inspect.getclosurevars(foo2)
# ClosureVars(nonlocals={}, globals={'colorsys': <module 'colorsys' from '...\\lib\\colorsys.py'>}, builtins={}, unbound={'rgb_to_hsv'})

Here it detected you are using a module's function.

Case 3:

def foo3(x):
return x*x # no - it has only referenced 'x' which is an input to foo3, so the code executed within the scope of foo3

inspect.getclosurevars(foo3)
# ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())

Here we see "nothing unusual".

Therefore, we can wrap this procedure in a function which looks if any of the fields (except for built-ins; i.e. foo can use abs and no problem) is non-empty:

import inspect

def references_sth_out_of_scope(fun):
closure_vars = inspect.getclosurevars(fun)
referenced = any(getattr(closure_vars, field) for field in closure_vars._fields if field != "builtins")
return referenced

Usage:

>>> references_sth_out_of_scope(foo1)
True

>>> references_sth_out_of_scope(foo2)
True

>>> references_sth_out_of_scope(foo3)
False

>>> references_sth_out_of_scope(references_sth_out_of_scope) # :)
True

Check whether a function is assigned or called

Ultimately, if you need two different effects for when a function's value is stored and when not, you more likely need two different functions and just document then accordingly.

You commented that "function is a data (file) reader. If function is called upon a filename, a global data variable is created, else it is assigned. " - no, silently creating a global variable "sometimes", is not a good design. If you want too, just create the global variable everytime. You'd be better using a global thread-local variable, so that a distinct value for the variable is used in each thread. Or, if you are using async-code, a context-local variable. Doing these would mitigate any unexpected changes to your global variable on the code expectng it to have the correct values after you call your function. And, as you can see, better yet, is just document that the function returns the read value, and leave it to the caller whether to assign that value to a global variable or not.

Back to the question:

Although there are far-off ways to detect if a return value is stored, it is not trivial, nor a thing expected to be done. The linked question, for example, uses advanced resources of the Python language to inspect the compiled code of the called function - this kind of resource is almost never used in code suitable for production, even in advanced library or frameworks, as its prone to be either too slow, or to break in sudden and unexpected ways. (For example, if in your production deployment, you configure some logging/traceback saving extension that would insert an a wrapper in your functions, it would mistake the callee function for the one in the framework - but just in production, not on the development machine). But more important than that, the linked code does not even start to check for corner cases, like, if the value is transformed prior to being stored (one might call a 'replace' method on it, or any other string method), or stored in a list or dictionary instead of in a local variable. Covering all possible use cases using that approach to the point of it being reliable is not possible at all.

But I am taking some time to elaborate an answer to clarify this should not be useful at all - if you understand how objects work in Python, you might find a better way to implement whatever you have in mind, without needing to know if the object is "stored" or not:

Any function in Python will return an object. Even if the object is "None". The fact is in Python, objects can be considered like "black boxes" until the point when they are used for something. When they are in fact used - not just stored in a variable, list, as a value in a dictionary, etc... when that happens, it is just a "black box" being stored, and the object can't be aware of being assigned a name or added to a list at all (maybe it is possible to code hooks in native code to check for increases in the reference counting of an object - but you'd need to do that at least in Cython if not in C - it very, very iffy, enough to say "it can't be aware").

But when an object is "used", that is another story. When you want to check what an object "is", even in the interactive terminal, or by printing it, the object's __repr__ or __str__ methods will be called. If you are making an operation with an object - trying to add it with another object with the "+" operator, or any other operator, special methods in the object are called.

If you are trying to save the object state to a file, it will be serialized - that will call methods used by the pickle protocol, or even __str__ itself, depending on the serialization used, and so on.

So, you can specialize a class and wrap all the desired "magic" methods, the ones defined in the language Data Model with names surrounded by __, to perform the action you'd like to do for when the object is "not stored" for example.

By the way, there is even a very simple method in the object that is called if it is not stored at all after the function call: the object's __del__ method will be called.

So, for simply having an effect when the object is not stored, you could dynamically create a subclass of whatever is the result of your function with a custom __del__ method, and perform your action there. This is still code that could have some objections in a production environment, but it is much more straightforward than interpreting the opcode of the calling function. But, of course, if the object is stored, when it is finally deleted in a later point in the code, the __del__ method would be triggered nonetheless. You can devise a mechanism to change an attribute in the object if any other special method is called before __del__, and if so, disable the side-effect - but as you can see, this is not trivial as well.

How do I test whether a variable is an integer value in python?

You can test arg2 type this way:

if (type(arg2) != int):
arg2=0


Related Topics



Leave a reply



Submit