如何解决Python弯曲和部分
在codewars.com上进行编程练习时,我遇到了exercise的currying函数和部分函数。
我是编程的新手,是该主题的新手,所以我在互联网上搜索了有关该主题的信息,并在解决该练习方面做了大量工作。但是,我现在偶然发现了我似乎无法克服的障碍,并在这里寻找正确方向的推动力。
该练习非常简单:编写一个函数,该函数可以咖喱化和/或分割任何输入函数,并在提供足够的输入参数后评估该输入函数。输入功能可以接受任意数量的输入参数。而且,curry / partial函数在调用方式上应该非常灵活,能够处理许多许多不同的调用方法。此外,允许使用比输入功能所需的输入更多的输入来调用curry / partial函数,在这种情况下,所有多余的输入都将被忽略。
我想到的代码如下:
from functools import partial
from inspect import signature
def curry_partial(func,*initial_args):
""" Generates a 'curried' version of a function. """
# Process any initial arguments that where given. If the number of arguments that are given exceeds
# minArgs (the number of input arguments that func needs),func is evaluated
minArgs = len(signature(func).parameters)
if initial_args:
if len(initial_args) >= minArgs:
return func(*initial_args[:minArgs])
func = partial(func,*initial_args)
minArgs = len(signature(func).parameters)
# Do the currying
def g(*myArgs):
nonlocal minArgs
# Evaluate function if we have the necessary amount of input arguments
if minArgs is not None and minArgs <= len(myArgs):
return func(*myArgs[:minArgs])
def f(*args):
nonlocal minArgs
newArgs = myArgs + args if args else myArgs
if minArgs is not None and minArgs <= len(newArgs):
return func(*newArgs[:minArgs])
else:
return g(*newArgs)
return f
return g
现在,当执行以下测试时,此代码将失败:
test.assert_equals(curry_partial(curry_partial(curry_partial(add,a),b),c),sum)
其中add = a + b + c(正确定义的函数),a = 1,b = 2,c = 3,总和= 6。
失败的原因是因为curry_partial(add,a)
返回了函数g
的函数句柄。在第二个调用curry_partial(<function_handle to g>,b)
中,计算minArgs = len(signature(func).parameters)
不能像我想要的那样工作,因为它现在将计算函数g
所需的输入参数个数(即{{1 }}:即1
),而不需要原始的*myArgs
数量。所以问题是,我该如何编写代码,以便跟踪原来的func
仍需要多少个输入参数(每次我使用给定的初始参数对函数进行部分划分时,都要减少该数量)。 / p>
关于编程和curring / partial,我还有很多要学习的东西,因此很可能我没有选择最方便的方法。但是我想学习。对我而言,此练习的难点在于将部分和咖喱结合使用,即在对遇到的任何初始参数进行部分分割的同时进行咖喱循环。
解决方法
尝试一下。
from inspect import signature
# Here `is_set` acts like a flip-flop
is_set = False
params = 0
def curry_partial(func,*partial_args):
"""
Required argument: func
Optional argument: partial_args
Return:
1) Result of the `func` if
`partial_args` contains
required number of items.
2) Function `wrapper` if `partial_args`
contains less than the required
number of items.
"""
global is_set,params
if not is_set:
is_set = True
# if func is already a value
# we should return it
try: params = len(signature(func).parameters)
except: return func
try:
is_set = False
return func(*partial_args[:params])
except:
is_set = True
def wrapper(*extra_args):
"""
Optional argument: extra_args
Return:
1) Result of the `func` if `args`
contains required number of
items.
2) Result of `curry_partial` if
`args` contains less than the
required number of items.
"""
args = (partial_args + extra_args)
try:
is_set = False
return func(*args[:params])
except:
is_set = True
return curry_partial(func,*args)
return wrapper
这确实不是很好。相反,您应该使用class
来完成所有内部工作,例如触发器(不要担心,我们在那里不需要任何触发器;-))。
只要有一个接受任意参数的函数,您就可以随时实例化该函数。但是这次,我把它留给你。
,我不确定 currying ,但是如果您需要一个简单的部分函数生成器,则可以尝试如下操作:
from functools import partial
from inspect import signature
def execute_or_partial(f,*args):
max = len(signature(f).parameters)
if len(args) >= max:
return f(*args[:max])
else:
return partial(f,*args)
s = lambda x,y,z: x + y + z
t = execute_or_partial(s,1)
u = execute_or_partial(t,2)
v = execute_or_partial(u,3)
print(v)
or
print(execute_or_partial(execute_or_partial(execute_or_partial(s,1),2),3))
即使它不能解决您原来的问题,请查看是否可以使用上述代码来减少代码重复(我不确定,但是我认为内部函数中有一些代码重复吗?);这将使后续问题更容易解决。
标准库中可能已经有解决此问题的函数。许多纯函数式语言(例如Haskell)都在语言中内置了此功能。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。