[英]Given a function that outputs a list, is it possible in Python to extract a function for each component?
For example, let's say I have a vector function mapping R2 to R2, for instance:例如,假设我有一个将 R2 映射到 R2 的向量函数,例如:
fun = lambda x1, x2: [x1**2 + 1, x2**2 - x1]
I'd like something that allows me to do this:我想要一些可以让我这样做的东西:
for f in components(fun):
print(f(2,3)) # Print first 5, then 7
Note: I'm not asking how to iterate over the components of one out, which is trivial (for val in f(2,3):), but how to iterate over the functions computing each component in the output.注意:我不是在问如何迭代 one out 的组件,这是微不足道的(对于 f(2,3): 中的 val),而是如何迭代计算输出中每个组件的函数。 Is this possible?
这可能吗?
Well you could do some trick, although you will need to explicitly state the expected number of components, since there is no way to tell how many outputs a Python function will have (unless you do something like "probing" the function with test values, which is also a possibility but more complex):好吧,您可以做一些技巧,尽管您需要明确说明预期的组件数量,因为无法确定 Python 函数将具有多少输出(除非您使用测试值执行“探测”函数之类的操作,这也是一种可能性,但更复杂):
def components(fun, n):
for i in range(n):
yield lambda *args, **kwargs: fun(*args, **kwargs)[i]
Then your loop could be:那么你的循环可能是:
for f in components(fun, 2):
print(f(2,3))
If you want to avoid repeating computations, you can use some kind of memoization.如果你想避免重复计算,你可以使用某种记忆。 In Python 3 you can use
lru_cache
:在 Python 3 中,您可以使用
lru_cache
:
from functools import lru_cache
def components(fun, n):
# You can tune lru_cache with a maxsize parameter
fun = lru_cache()(fun)
for i in range(n):
yield lambda *args, **kwargs: fun(*args, **kwargs)[i]
I don't think it's possible to do what you ask, since in this case there are not two different functions.我认为不可能按照您的要求进行操作,因为在这种情况下没有两个不同的功能。 It is one function with a list as output, taking the two arguments as input.
它是一个以列表作为输出的函数,将两个参数作为输入。
You could make two different functions and concatenate this in one big function to get what you acces to two separate functions:您可以创建两个不同的函数并将其连接到一个大函数中,以获得您对两个单独函数的访问权限:
fun_1 = lambda x1: x1**2 + 1
fun_2 = lambda x1, x2: x2**2 - x1
fun = lambda x1, x2: [fun_1(x1), fun_2(x1, x2)]
I found out sympy converts such functions into a list of sympy expressions, so I ended up doing the following:我发现 sympy 将此类函数转换为 sympy 表达式列表,因此我最终执行了以下操作:
from inspect import signature
import sympy
def components(function):
# Determine number of argument function takes
n_args = len(signature(function).parameters)
# Allocate n symbols like x1, x2, ..., xn
symbols = [sympy.Symbol("x"+str(i)) for i in range(1, n_args+1)]
# Get list of expressions for the components of the input function
expression_list = function(*symbols)
# Convert each expression into a function and yield
for expr in expression_list:
yield lambda *args: sympy.lambdify(symbols, expr)(*args)
return None
fun = lambda x1, x2: [x1**2 + 1, x2**2 - x1]
for f in components(fun):
print(f(2,3)) # prints 5, 7
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.