18

I'm working on a project, which contains several modules. Simplifying the problem, there is some variable x. Sometimes it may be int or float or list. But it may be a lambda function, and should be treated in different way. How to check that variable x is a lambda?

For example

>>> x = 3
>>> type(x)
<type 'int'>
>>> type(x) is int
True
>>> x = 3.4
>>> type(x)
<type 'float'>
>>> type(x) is float
True
>>> x = lambda d:d*d
>>> type(x)
<type 'function'>
>>> type(x) is lambda
  File "<stdin>", line 1
    type(x) is lambda
                    ^
SyntaxError: invalid syntax
>>> type(x) is function
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'function' is not defined
>>> 
rth
  • 2,946
  • 1
  • 22
  • 27
  • Closely related: [How do I detect whether a Python variable is a function?](https://stackoverflow.com/questions/624926/how-do-i-detect-whether-a-python-variable-is-a-function) – jpp Jan 08 '19 at 14:56

3 Answers3

28

You need to use types.LambdaType or types.FunctionType to make sure that the object is a function object like this

x = lambda d:d*d
import types
print type(x) is types.LambdaType
# True
print isinstance(x, types.LambdaType)
# True

and then you need to check the name as well to make sure that we are dealing with a lambda function, like this

x = lambda x: None
def y(): pass
print y.__name__
# y
print x.__name__
# <lambda>

So, we put together both these checks like this

def is_lambda_function(obj):
    return isinstance(obj, types.LambdaType) and obj.__name__ == "<lambda>"

As @Blckknght suggests, if you want to check if the object is just a callable object, then you can use the builtin callable function.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 2
    `isinstance(x, types.LambdaType)` looks more idiomatic. – bereal May 25 '14 at 05:50
  • 10
    It's worth noting that `types.LambdaType` is an alias for `types.FunctionType`. There's no (easy or reliable) way to tell the difference between a lambda function and one created with `def`. – Blckknght May 25 '14 at 05:53
  • 2
    @Blckknght That is why we need to check the `__name__` as well :-) – thefourtheye May 25 '14 at 05:54
  • so it should be to step procedure type(x) is types.LambdaType and x.__name__ == ''. Right? – rth May 25 '14 at 05:54
  • @rth You are correct. I included a `is_lambda_function` as well, please check. – thefourtheye May 25 '14 at 05:54
  • 5
    Ah, I see I hadn't payed enough attention to the end of the answer, and you've already addressed the issue of lambdas versus regular functions. I'd suggest though that there probably isn't much need to tell the difference. If your code really cares how a given function was defined, you're probably doing it wrong. Most of the time you should use "duck typing" rather than strict type checks. If you expect a function, accept anything that is callable (such as a class, or an instance of a class with a `__call__` method). If you do need to check up front, use the builtin `callable` function. – Blckknght May 25 '14 at 05:57
  • @Blckknght Thanks :-) I included that as well in the answer. – thefourtheye May 25 '14 at 06:01
  • `__name__` can be changed. Alternatively, use `__code__.co_name`, which contains the name of the function/lambda at the time it was compiled and is read-only. See https://stackoverflow.com/questions/54094263/how-to-find-out-if-a-function-has-been-declared-by-lambda-or-def/64301482#64301482 – Peter Nowee Oct 11 '20 at 07:23
2

If you prefer the typing module, use Callable:

In [1]: from typing import Callable
In [2]: isinstance(lambda: None, Callable)
Out[2]: True
crypdick
  • 16,152
  • 7
  • 51
  • 74
  • what is the difference between your solution and @Blckknght suggestion to use `callable` built-in function? – rth Jan 17 '21 at 20:21
  • 1
    @rth you can't use `callable()` for typing hinting your signatures – crypdick Jan 18 '21 at 18:13
  • A regular function (not lambda) also returns True: `def x(): pass`, `isinstance(x, Callable)` ->`True`. So I don't see any advantage of your answer vs @thefourtheye one. – rth Jan 18 '21 at 18:27
  • 1) your question should specify that you want to discriminate between lambda functions and ordinary functions if that is a requirement. 2) `callable(lambda: None) == True` – crypdick Jan 18 '21 at 18:33
  • I don't know how to make more specific, it is in the title **How to check that variable is a lambda function** :) Thank you for additional answer! – rth Jan 20 '21 at 01:27
  • This isn't exactly correct. This gets you any *callable*, not function objects specifically. And generally, if you want to check if something is callable, you should just use the builtin `callable`, e.g. `callable(lambda: None)`. Indeed, I am surprised this even worked, and it only works because this inherits from `collections.abc.Callable` which would probably be what you want to use for runtime checks anyway... – juanpa.arrivillaga Feb 01 '21 at 09:10
  • @juanpa.arrivillaga I testing using the built-in `callable` in place of `typing.Callable` to type hint in a function signature. That did not work with the runtime type validator we use (`typeguard`). – crypdick Feb 01 '21 at 15:53
  • @crypdick no, *it isn't a type* it's a function that checks if an object is callable, it's for *runtime type checking* not static analysis. – juanpa.arrivillaga Feb 01 '21 at 16:58
0

Can consider the following:

type(x) == type(lambda x:x)
Adriaan
  • 17,741
  • 7
  • 42
  • 75
  • 1
    Welcome to Stack Overflow! Please read [answer] and [edit] your answer to contain an explanation as to why this code would actually solve the problem at hand. Always remember that you're not only solving the problem, but are also educating the OP and any future readers of this post. – Adriaan Mar 21 '23 at 07:50