Python 嵌套柯里化
Python nested currying
我试图解决代码战问题 here,但遇到了一点困难。我相信我应该在 Python.
中使用嵌套柯里化
让我们以添加为例。让我们进一步限制问题,并在右侧进行嵌套添加,即编写一个添加函数,使得
print((add)(3)(add)(5)(4))
打印 12。
应该可以根据需要将其嵌套得尽可能深,例如我要
print((add)(add)(3)(4)(add)(5)(6))
应该给我18。
到目前为止我做了什么 -
我最初的尝试是使用下面的嵌套函数 -
def add_helper():
current_sum = 0
def inner(inp):
if isinstance(inp, int):
nonlocal current_sum
current_sum += inp
print(f"current_sum = {current_sum}")
return inner
return inner
add = add_helper()
但是,这并不能解决问题。相反,我得到以下输出,因为当我执行类似 print((add)(add)(3)(4)(add)(5)(6))
的操作时
current_sum = 3
current_sum = 7
current_sum = 12
current_sum = 18
<function add_helper.<locals>.inner at 0x...>
有谁知道我必须如何更改我的功能,以便我只是 return 18,因为该功能会知道它已“完成”?
任何帮助将不胜感激!
更新
看了之后,我目前有以下内容-
def add_helper():
val = 0
ops_so_far = []
def inner(inp):
if isinstance(inp, int):
nonlocal val
val += inp
return inner
else:
ops_so_far.append(("+", val))
inp.set_ops_so_far(ops_so_far)
return inp
def set_ops_so_far(inp_list):
nonlocal ops_so_far
ops_so_far = inp_list
def get_val():
nonlocal val
return val
def get_ops_so_far():
nonlocal ops_so_far
return ops_so_far
inner.get_ops_so_far = get_ops_so_far
inner.set_ops_so_far = set_ops_so_far
inner.get_val = get_val
return inner
def mul_helper():
val = 1
ops_so_far = []
def inner(inp):
if isinstance(inp, int):
nonlocal val
val *= inp
return inner
else:
ops_so_far.append(("*", val))
inp.set_ops_so_far(ops_so_far)
return inp
def get_ops_so_far():
nonlocal ops_so_far
return ops_so_far
def set_ops_so_far(inp_list):
nonlocal ops_so_far
ops_so_far = inp_list
def get_val():
nonlocal val
return val
inner.get_ops_so_far = get_ops_so_far
inner.get_val = get_val
inner.set_ops_so_far = set_ops_so_far
return inner
add = add_helper()
mul = mul_helper()
现在当我这样做时
res = (add)(add)(3)(4)(mul)(5)(6)
print(res.get_ops_so_far())
print(res.get_val())
我明白了
[('+', 0), ('+', 7)]
30
仍然不确定这是否是正确的方向?
这就是我为那些仍在展望未来的人解决问题的方法 -
from copy import deepcopy
def start(arg):
def start_evalutaion(_arg, eval_stack, variables):
new_eval_stack = deepcopy(eval_stack)
new_variables = deepcopy(variables)
to_ret = evaluate_stack(_arg, new_eval_stack, new_variables)
if to_ret is not None:
return to_ret
def inner(inner_arg):
return start_evalutaion(
inner_arg, new_eval_stack, new_variables
)
return inner
return start_evalutaion(arg, [], dict())
add = lambda a, b, variables: variables.get(a, a) + variables.get(b, b)
sub = lambda a, b, variables: variables.get(a, a) - variables.get(b, b)
mul = lambda a, b, variables: variables.get(a, a) * variables.get(b, b)
div = lambda a, b, variables: variables.get(a, a) // variables.get(b, b)
def let(name, val, variables):
variables[name] = val
return
def return_(val, variables):
return variables.get(val, val)
def evaluate_stack(_arg, eval_stack, variables):
if callable(_arg):
if _arg.__name__ == "return_":
req_args = 1
else:
req_args = 2
eval_stack.append((_arg, req_args, []))
else:
while True:
func_to_eval, req_args, args_so_far = eval_stack[-1]
args_so_far.append(_arg)
if len(args_so_far) == req_args:
eval_stack.pop()
_arg = func_to_eval(*args_so_far, variables)
if func_to_eval.__name__ == "return_":
return _arg
elif _arg is None:
break
else:
break
通过所有测试用例
我试图解决代码战问题 here,但遇到了一点困难。我相信我应该在 Python.
中使用嵌套柯里化让我们以添加为例。让我们进一步限制问题,并在右侧进行嵌套添加,即编写一个添加函数,使得
print((add)(3)(add)(5)(4))
打印 12。
应该可以根据需要将其嵌套得尽可能深,例如我要
print((add)(add)(3)(4)(add)(5)(6))
应该给我18。
到目前为止我做了什么 -
我最初的尝试是使用下面的嵌套函数 -
def add_helper():
current_sum = 0
def inner(inp):
if isinstance(inp, int):
nonlocal current_sum
current_sum += inp
print(f"current_sum = {current_sum}")
return inner
return inner
add = add_helper()
但是,这并不能解决问题。相反,我得到以下输出,因为当我执行类似 print((add)(add)(3)(4)(add)(5)(6))
current_sum = 3
current_sum = 7
current_sum = 12
current_sum = 18
<function add_helper.<locals>.inner at 0x...>
有谁知道我必须如何更改我的功能,以便我只是 return 18,因为该功能会知道它已“完成”?
任何帮助将不胜感激!
更新
看了
def add_helper():
val = 0
ops_so_far = []
def inner(inp):
if isinstance(inp, int):
nonlocal val
val += inp
return inner
else:
ops_so_far.append(("+", val))
inp.set_ops_so_far(ops_so_far)
return inp
def set_ops_so_far(inp_list):
nonlocal ops_so_far
ops_so_far = inp_list
def get_val():
nonlocal val
return val
def get_ops_so_far():
nonlocal ops_so_far
return ops_so_far
inner.get_ops_so_far = get_ops_so_far
inner.set_ops_so_far = set_ops_so_far
inner.get_val = get_val
return inner
def mul_helper():
val = 1
ops_so_far = []
def inner(inp):
if isinstance(inp, int):
nonlocal val
val *= inp
return inner
else:
ops_so_far.append(("*", val))
inp.set_ops_so_far(ops_so_far)
return inp
def get_ops_so_far():
nonlocal ops_so_far
return ops_so_far
def set_ops_so_far(inp_list):
nonlocal ops_so_far
ops_so_far = inp_list
def get_val():
nonlocal val
return val
inner.get_ops_so_far = get_ops_so_far
inner.get_val = get_val
inner.set_ops_so_far = set_ops_so_far
return inner
add = add_helper()
mul = mul_helper()
现在当我这样做时
res = (add)(add)(3)(4)(mul)(5)(6)
print(res.get_ops_so_far())
print(res.get_val())
我明白了
[('+', 0), ('+', 7)]
30
仍然不确定这是否是正确的方向?
这就是我为那些仍在展望未来的人解决问题的方法 -
from copy import deepcopy
def start(arg):
def start_evalutaion(_arg, eval_stack, variables):
new_eval_stack = deepcopy(eval_stack)
new_variables = deepcopy(variables)
to_ret = evaluate_stack(_arg, new_eval_stack, new_variables)
if to_ret is not None:
return to_ret
def inner(inner_arg):
return start_evalutaion(
inner_arg, new_eval_stack, new_variables
)
return inner
return start_evalutaion(arg, [], dict())
add = lambda a, b, variables: variables.get(a, a) + variables.get(b, b)
sub = lambda a, b, variables: variables.get(a, a) - variables.get(b, b)
mul = lambda a, b, variables: variables.get(a, a) * variables.get(b, b)
div = lambda a, b, variables: variables.get(a, a) // variables.get(b, b)
def let(name, val, variables):
variables[name] = val
return
def return_(val, variables):
return variables.get(val, val)
def evaluate_stack(_arg, eval_stack, variables):
if callable(_arg):
if _arg.__name__ == "return_":
req_args = 1
else:
req_args = 2
eval_stack.append((_arg, req_args, []))
else:
while True:
func_to_eval, req_args, args_so_far = eval_stack[-1]
args_so_far.append(_arg)
if len(args_so_far) == req_args:
eval_stack.pop()
_arg = func_to_eval(*args_so_far, variables)
if func_to_eval.__name__ == "return_":
return _arg
elif _arg is None:
break
else:
break
通过所有测试用例