如何在给定的参数位置使用函数

时间:2019-07-10 16:22:09

标签: python functional-programming currying

是否可以在用户定义的第n个位置使用函数? Functool的partial函数可以处理对

的多个参数的部分求值
from functools import partial

def f(x,y,z):
    return [x,y,z]

然后

partial(f,1)(2,3)
  

[1,2,3]

partial(f,1,2)(3)
  

[1,2,3]

是否有可能在给定的论点位置咖喱?

curry_at(f,n)

如此

curry_at(f,2)(1,3)(2)

给予

  

[1,2,3]

在哪里,我想与可能的* arg和** kwarg保持一致,n应该不大于常规参数的数量?

是否存在枚举参数以将前缀和后缀参数分隔到第n个插槽的方法?

2 个答案:

答案 0 :(得分:1)

推荐这样的函数并不常见,但是在这种情况下,我认为最好是具有一些重复的静态定义,而不是依赖于复杂行为难以验证的动态函数-< / p>

def apply_at_1 (f, *a, **kw):
  return lambda x, *a2, **kw2: \
    f(x, *a, *a2, **kw, **kw2)

def apply_at_2 (f, *a, **kw):
  return lambda x, y, *a2, **kw2: \
    f(x, y, *a, *a2, **kw, **kw2)

def apply_at_3 (f, *a, **kw):
  return lambda x, y, z, *a2, **kw2: \
    f(x, y, z, *a, *a2, **kw, **kw2)

def dummy (a, b, c, d, *more):
  print (a, b, c, d, *more)

apply_at_1(dummy, 2, 3, 4)(1, 5, 6, 7, 8)
# 1 2 3 4 5 6 7 8

apply_at_2(dummy, 3, 4, 5)(1, 2, 6, 7, 8)
# 1 2 3 4 5 6 7 8

apply_at_3(dummy, 4, 5, 6)(1, 2, 3, 7, 8)
# 1 2 3 4 5 6 7 8

当然,动态函数允许您在 any 位置应用参数,但是如果您需要在位置4(第五参数)应用参数,也许是时候考虑重构了。在这种情况下,我认为最好设定一个合理的限制,然后对自己进行约束。

由于键入的原因,其他功能语言也会执行类似的操作。考虑Haskell的liftA2liftA3liftA4等。或者Elm的List.mapList.map2List.map3List.map4等。

有时候,KISS会更容易。


这是partial版,支持通配符__-

def __ ():
  return None;

def partial (f, *a):
  def combine (a, b):
    if not a:
      return b
    elif a[0] is __:
      return (b[0], *combine(a[1:], b[1:]))
    else:
      return (a[0], *combine(a[1:], b))
  return lambda *b: f(*combine(a,b))

def dummy (a, b, c, d, *more):
  print (a, b, c, d, *more)

partial(dummy, 1, __, __, 4)(2, 3, 5, 6, 7, 8) 
# 1 2 3 4 5 6 7 8

partial(dummy, __, __, 3, __, __, 6, 7, 8)(1, 2, 4, 5)
# 1 2 3 4 5 6 7 8

答案 1 :(得分:0)

我尝试了使用索引和for循环的workarond,希望对您有所帮助:

from functools import partial

def curry_at(funtion,parameter,index,*args):
  h = funtion
  index-=1
  ls = list(args)
  ls.insert(index,parameter)
  for arg in ls:
      h = partial(h,arg)
  return h()

a = curry_at(f,'a',2,'c','d')

b = curry_at(f,2,2,1,3)
  

a

     

['c','a','d']

     

b

     

[1,2,3]