Python 如何确定函数是由'lambda'还是'def'声明的?
如果我声明两个函数Python 如何确定函数是由'lambda'还是'def'声明的?,python,function,lambda,types,function-declaration,Python,Function,Lambda,Types,Function Declaration,如果我声明两个函数a和b: def a(x): return x**2 b = lambda x: x**2 我不能用type来区分它们,因为它们都是同一类型的 assert type(a) == type(b) 另外,types.LambdaType也没有帮助: >>> import types >>> isinstance(a, types.LambdaType) True >>> isinstance(b, types.L
a
和b
:
def a(x):
return x**2
b = lambda x: x**2
我不能用type
来区分它们,因为它们都是同一类型的
assert type(a) == type(b)
另外,types.LambdaType
也没有帮助:
>>> import types
>>> isinstance(a, types.LambdaType)
True
>>> isinstance(b, types.LambdaType)
True
可以使用\uuuu name\uuuuu
如下:
def is_lambda_function(function):
return function.__name__ == "<lambda>"
>>> is_lambda_function(a)
False
>>> is_lambda_function(b)
True
有没有一种方法可以产生比
\uu name\uuu
属性更可靠的结果?好吧,在Python3中无法可靠地生成结果
Python2用于定义一系列函数类型。因此,方法、lambda和普通函数都有各自的类型
Python3只有一种类型,即function
。使用def
和lambda
声明一个常规函数确实有不同的副作用:def
将函数名(和限定名)设置为函数名,并可以设置docstring,而lambda
将名称(和限定名)设置为
,并将docstring设置为无。但这是可以改变的
如果函数是从常规Python源代码加载的(并且不是在交互环境中键入的),则inspect
模块允许访问原始Python代码:
import inspect
def f(x):
return x**2
g = lambda x: x**2
def is_lambda_func(f):
"""Tests whether f was declared as a lambda.
Returns: True for a lambda, False for a function or method declared with def
Raises:
TypeError if f in not a function
OSError('could not get source code') if f was not declared in a Python module
but (for example) in an interactive session
"""
if not inspect.isfunction(f):
raise TypeError('not a function')
src = inspect.getsource(f)
return not src.startswith('def') and not src.startswith('@') # provision for decorated funcs
g.__name__ = 'g'
g.__qualname__ = 'g'
print(f, is_lambda_func(f))
print(g, is_lambda_func(g))
这将打印:
<function f at 0x00000253957B7840> False
<function g at 0x00000253957B78C8> True
我借此机会潜入水中,看看是否能找到什么,恐怕我不得不说:你不能 简单地说,这是一个lambda在解释器中的旅程:
expr\u ty
转换为适当的类型(,在我们的例子中)从这里,我看不到任何特定于lambdas的东西。这一点,再加上Python允许您修改几乎所有对象属性的事实,使我/我们相信您想要做的事情是不可能的。您可以检查
\uuuuuuuuuuuuuuuuu.co\u name
。它包含编译函数/lambda时的名称:
defa(x):
返回x**2
b=λx:x**2
def是λ函数(f):
返回f.。\u代码\u.co\u名称=“”
>>>is_lambda_函数(a)
假的
>>>is_lambda_函数(b)
真的
而且,与\uuuuu name\uuuuuu
相反,\uuuu code\uuuu.co\u name
是
>>a.。\uuuuu name=“”
>>>b.uuu name_uuu=“b”
>>>a.。_uu代码_uu.co_u名称=“”
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:只读属性
>>>b._code_u.co_name=“b”
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:只读属性
。。。因此,结果将保持不变:
>>是lambda函数(a)
假的
>>>is_lambda_函数(b)
真的
是否有任何实际使用案例需要此功能?连同上面的其他注释,它是def还是lambda有什么区别?@JaredSmith,例如,Django无法序列化lambda。@jpp:IMHO它不是重复的!另一个问题的公认答案显然是指Python2,而Python3现在更常用。而且它不能应用在Python3中……您的用例是什么?为了进一步说明您的答案:由于def
和lambda
产生无法区分的对象(特别是因为您可以自由编辑\uu name\uuuuuuuu
和\uuuuuu qualname\uuuuu
),那么不仅“不可能”执行OP要求的操作,而且没有意义。如何区分由列表理解生成的列表与由list
函数创建并由for
循环填充的列表之间的区别?如何区分单引号生成的字符串与双引号生成的字符串之间的区别?不能这样做,因为除了源代码级别之外,没有区别。
<function f at 0x00000253957B7840> False
<function g at 0x00000253957B78C8> True
>>> g = lambda x: 3*x
>>> g.__qualname__ = "g"
>>> pickle.dumps(g)
b'\x80\x03c__main__\ng\nq\x00.'