[英]Python nested currying
I was trying to solve a codewars problem here , and I got a bit stuck.我试图在 这里解决一个 codewars 问题,但我有点卡住了。 I believe I should be using nested currying in Python.我相信我应该在 Python 中使用嵌套柯里化。
Let us just take the case of add.让我们以添加为例。 Let us constrain the problem even more, and just get nested add working on the right hand side, ie write an add function such that让我们进一步限制问题,让嵌套加法在右侧工作,即写一个加法 function 这样
print((add)(3)(add)(5)(4))
prints 12.打印 12。
It should be possible to nest it as deep as required, for eg I want应该可以根据需要将它嵌套得尽可能深,例如我想要
print((add)(add)(3)(4)(add)(5)(6))
should give me 18.应该给我18。
What I have done so far -到目前为止我所做的 -
My initial attempt is to use the following nested function -我最初的尝试是使用以下嵌套的 function -
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()
However, this does not do the trick.但是,这并不能解决问题。 Instead, I get the following output, for when I do something like print((add)(add)(3)(4)(add)(5)(6))
相反,我得到以下 output,因为当我执行类似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...>
Does anyone know how I have to change my function so that I just return 18, because the function will know it is "done"?有谁知道我必须如何更改我的 function 以便我只返回 18,因为 function 会知道它已“完成”?
Any help will be appreciated!任何帮助将不胜感激!
UPDATE更新
After looking at Bharel's comments , I have the following so far -在查看了Bharel 的评论之后,到目前为止我有以下内容 -
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()
and now when I do现在当我这样做
res = (add)(add)(3)(4)(mul)(5)(6)
print(res.get_ops_so_far())
print(res.get_val())
I get我明白了
[('+', 0), ('+', 7)]
30
Still not sure if this is the correct direction to be following?仍然不确定这是否是正确的方向?
This is how I solved it for anyone still looking in the future -这就是我为仍在寻找未来的任何人解决它的方式 -
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
Passes all testcases通过所有测试用例
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.