如何在 lambda 函数中获取函数对象
How can I get the function object inside a lambda function
抱歉,如果这很蹩脚,但我是 Python 的新手。
正如在 Python 中一样,一切都是对象,我假设在每个对象中,对象本身都可以通过某种方式获得。在对象方法中,self
变量包含它。从对象引用中可以得到 class 对象(如 type(self)
)。但是如何将其放入 lambda 中?
我可以算出一个正常的函数:
import inspect
def named_func():
func_name = inspect.stack()[0].function
func_obj = inspect.stack()[1].frame.f_locals[func_name]
print(func_name, func_obj, func_obj.xxx)
named_func.xxx = 15
named_func()
输出如下所示:
named_func <function named_func at 0x7f56e368c2f0> 15
不幸的是,在 lambda 中 inspect.stack()[0].function
在 lambda 内部给出了 <lambda>
。
有没有办法在 lambda 中获取函数对象?
有没有办法直接获取函数对象(不使用函数名称)?
我想象的__self__
,但是不行
更新
我在 lambda 中尝试过这样的事情:
lambda_func = lambda : inspect.stack()[0]
lambda_func.xxx = 2
print(lambda_func())
这会打印:
FrameInfo(frame=<frame at 0x7f3eee8a6378, file './test_obj.py', line 74, code <lambda>>, filename='./test_obj.py', lineno=74, function='<lambda>', code_context=['lambda_func = lambda : inspect.stack()[0]\n'], index=0)
但是例如,在这种情况下有没有办法获取 lambda 对象字段 xxx
?为此,应该以某种方式获取 lambda 对象。
注意,这不是问题的 efficient/pragmatic 解决方案。这不是关于如何编写实际软件的建议。它只是介绍如何在不将其分配给变量名的情况下从 lambda 访问 lambda 引用。这是一个非常hacky的答案。
只有遵循 answer found here
的建议才能完全正确地工作
简而言之,给定 stack
你可以找到 code
对象,然后使用 gc
模块你可以找到对你的 lambda 的引用。
@Tomalak 的阶乘 lambda 示例!
import gc
import inspect
def current_lambda():
lambda_code = inspect.stack()[1].frame.f_code
candidates = [
referrer
for referrer in gc.get_referrers(lambda_code)
if inspect.isfunction(referrer)
and referrer.__code__ is lambda_code
]
if len(candidates) != 1:
raise ValueError(
"Multiple candidates found! Cannot determine correct function!"
)
return candidates[0]
print((lambda n: 1 if n < 2 else n * current_lambda()(n - 1))(5))
产出
120
回顾你的例子:
lambda_func = lambda: current_lambda().xxx
lambda_func.xxx = 10
print(lambda_func())
输出:
10
我们现在可以使用新的 python 语法使其更短且更易于阅读,而无需为此目的定义新函数。
您可以在下面找到两个示例:
斐波那契数列:
(f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
阶乘:
(f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
我们使用 :=
命名 lambda:直接在 lambda 本身中使用该名称,并立即将其作为匿名函数调用。
所以在你的特定用例中它会给出类似的东西:
print((f:=lambda: f.__hash__())()) # prints the hash for example
您现在可以使用 f
变量(在 lambda 中)做任何您想做的事情。
但实际上,如果您不介意代码多行,您也可以直接使用名称并执行类似的操作:
f = lambda : f.xxx
f.xxx = 2
print(f())
(有关此 :=
运算符的更多信息,请参阅 https://www.python.org/dev/peps/pep-0572)
抱歉,如果这很蹩脚,但我是 Python 的新手。
正如在 Python 中一样,一切都是对象,我假设在每个对象中,对象本身都可以通过某种方式获得。在对象方法中,self
变量包含它。从对象引用中可以得到 class 对象(如 type(self)
)。但是如何将其放入 lambda 中?
我可以算出一个正常的函数:
import inspect
def named_func():
func_name = inspect.stack()[0].function
func_obj = inspect.stack()[1].frame.f_locals[func_name]
print(func_name, func_obj, func_obj.xxx)
named_func.xxx = 15
named_func()
输出如下所示:
named_func <function named_func at 0x7f56e368c2f0> 15
不幸的是,在 lambda 中 inspect.stack()[0].function
在 lambda 内部给出了 <lambda>
。
有没有办法在 lambda 中获取函数对象?
有没有办法直接获取函数对象(不使用函数名称)?
我想象的__self__
,但是不行
更新
我在 lambda 中尝试过这样的事情:
lambda_func = lambda : inspect.stack()[0]
lambda_func.xxx = 2
print(lambda_func())
这会打印:
FrameInfo(frame=<frame at 0x7f3eee8a6378, file './test_obj.py', line 74, code <lambda>>, filename='./test_obj.py', lineno=74, function='<lambda>', code_context=['lambda_func = lambda : inspect.stack()[0]\n'], index=0)
但是例如,在这种情况下有没有办法获取 lambda 对象字段 xxx
?为此,应该以某种方式获取 lambda 对象。
注意,这不是问题的 efficient/pragmatic 解决方案。这不是关于如何编写实际软件的建议。它只是介绍如何在不将其分配给变量名的情况下从 lambda 访问 lambda 引用。这是一个非常hacky的答案。
只有遵循 answer found here
的建议才能完全正确地工作简而言之,给定 stack
你可以找到 code
对象,然后使用 gc
模块你可以找到对你的 lambda 的引用。
@Tomalak 的阶乘 lambda 示例!
import gc
import inspect
def current_lambda():
lambda_code = inspect.stack()[1].frame.f_code
candidates = [
referrer
for referrer in gc.get_referrers(lambda_code)
if inspect.isfunction(referrer)
and referrer.__code__ is lambda_code
]
if len(candidates) != 1:
raise ValueError(
"Multiple candidates found! Cannot determine correct function!"
)
return candidates[0]
print((lambda n: 1 if n < 2 else n * current_lambda()(n - 1))(5))
产出
120
回顾你的例子:
lambda_func = lambda: current_lambda().xxx
lambda_func.xxx = 10
print(lambda_func())
输出:
10
我们现在可以使用新的 python 语法使其更短且更易于阅读,而无需为此目的定义新函数。
您可以在下面找到两个示例:
斐波那契数列:
(f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
阶乘:
(f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
我们使用 :=
命名 lambda:直接在 lambda 本身中使用该名称,并立即将其作为匿名函数调用。
所以在你的特定用例中它会给出类似的东西:
print((f:=lambda: f.__hash__())()) # prints the hash for example
您现在可以使用 f
变量(在 lambda 中)做任何您想做的事情。
但实际上,如果您不介意代码多行,您也可以直接使用名称并执行类似的操作:
f = lambda : f.xxx
f.xxx = 2
print(f())
(有关此 :=
运算符的更多信息,请参阅 https://www.python.org/dev/peps/pep-0572)