请考虑以下两个功能:
def f1():
return "potato"
f2 = lambda: "potato"
f2.__name__ = f2.__qualname__ = "f2"
简短地对原始源代码进行内省,是否有任何方法可以检测到f1
是def并且f2
是lambda?
>>> black_magic(f1)
"def"
>>> black_magic(f2)
"lambda"
答案 0 :(得分:15)
您可以检查代码对象的名称。与函数名称不同,不能重新分配代码对象的名称。 Lambda的代码对象的名称仍为'<lambda>'
:
>>> x = lambda: 5
>>> x.__name__ = 'foo'
>>> x.__name__
'foo'
>>> x.__code__.co_name
'<lambda>'
>>> x.__code__.co_name = 'foo'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
def
语句无法定义代码对象名称为'<lambda>'
的函数。在创建后可以 替换函数的代码对象,但是这样做很少见,而且很奇怪,以至于不值得处理。同样,这将无法处理通过手动调用types.FunctionType
或types.CodeType
创建的函数或代码对象。我看不到任何处理__code__
重新分配或手动创建的函数和代码对象的好方法。
答案 1 :(得分:-1)
您可以使用ast.NodeVisitor来实现目标,而无需通过在源代码层上进行操作来对任何函数的硬编码,使用它可以标识 ALL Lambda,{{ 3}},FunctionDef函数定义并打印出其位置,名称等。请参见下面的代码示例:
import ast
class FunctionsVisitor(ast.NodeVisitor):
def visit_Lambda(self, node):
print(type(node).__name__, ', line no:', node.lineno)
def visit_FunctionDef(self, node):
print(type(node).__name__, ':', node.name)
def visit_AsyncFunctionDef(self, node):
print(type(node).__name__, ':', node.name)
def visit_Assign(self, node):
if type(node.value) is ast.Lambda:
print("Lambda assignment to: {}.".format([target.id for target in node.targets]))
self.generic_visit(node)
def visit_ClassDef(self, node):
# Remove that method to analyse functions visitor and functions in other classes.
pass
def f1():
return "potato"
f2 = f3 = lambda: "potato"
f5 = lambda: "potato"
async def f6():
return "potato"
# Actually you can define ast logic in separate file and process sources file in it.
with open(__file__) as sources:
tree = ast.parse(sources.read())
FunctionsVisitor().visit(tree)
以下代码的输出如下:
FunctionDef : f1
Lambda assignment to: ['f2', 'f3'].
Lambda , line no: 27
Lambda assignment to: ['f5'].
Lambda , line no: 28
AsyncFunctionDef : f6
答案 2 :(得分:-2)
这里
#include <iostream>
template <typename T>
constexpr std::size_t doSomething ()
{ return sizeof(T); }
template <typename ... Ts>
constexpr int fakeFunc (Ts const & ...)
{ return 0; }
template <typename ... Ts>
constexpr int doStuff ()
{ return fakeFunc( doSomething<Ts>()... ); }
int main()
{
constexpr int a { doStuff<char, short, int, long, long long>() };
(void)a;
}
输出
def f1():
return "potato"
f2 = lambda: "potato"
def is_lambda(f):
return '<lambda>' in str(f.__code__)
print(is_lambda(f1))
print(is_lambda(f2))