管道和函数的部分应用,为什么在Python中如此



Python的主要优点之一是它的表现力。该语言的功能使您可以简洁地描述数据转换。在我看来,Python缺少一些工具,这些工具将有助于更方便地描述数据转换并补充语言的功能组件,尤其是“功能管道”及其部分应用程序。因此,在这篇文章中,我将通过实验来研究这些资金的可能性和必要性。我以多种方式来批评。享受阅读!



简要介绍Python中的FP以及为什么没有足够的管道(例如)



Python有一些非常方便的基本工具,例如map(),reduce(),filter(),lambda函数,迭代器和生成器。我建议每个不熟悉这篇文章的人通常,所有这些都使您可以快速自然地描述列表,元组等的转换。很多时候(和我以及我的朋友pythonists)会发生什么单线-本质上是一组顺序转换,过滤器,例如:

带有CodeWars的Kata:查找



ñ[一种b]ñ=0Ëñññ一世一世 ñ一世 -第n个第i位



任务很简单,不幸的是(幸运的是,对于这篇文章来说),没有比正面更好的解决方案了。



我的决定:



def sum_dig_pow(a, b): # range(a, b + 1) will be studied by the function
    powered_sum = lambda x: sum([v**(i+1) for i,v in enumerate(map(lambda x: int(x), list(str(x))))])
    return [i for i in range(a,b+1) if powered_sum(i)==i]


照原样使用FP的方法,我们会“从内而外”得到一个括号地狱。管道可以解决该问题。



功能管道



sim是我的意思,在理想情况下(“ |”运算符是个人喜好):



# f3(f2(f1(x)))
f1 | f2 | f3 >> x
pipeline = f1 | f2 | f3 
pipeline(x)
pipeline2 = f4 | f5
pipeline3 = pipeline | pipeline2 | f6
...


然后powered_sum可以变成(代码不起作用):



powered_sum = str | list | map(lambda x: int(x), *args) | enumerate | [v**(i+1) for i,v in *args] | sum


对我来说,这段代码更容易编写和阅读。args一般看起来很陌生。实际上,事实证明,这样做(没有任何理想)不会爬进python的胆量:



from copy import deepcopy

class CreatePipeline:
    def __init__(self, data=None):
        self.stack = []
        if data is not None:
            self.args = data

    def __or__(self, f):
        new = deepcopy(self)
        new.stack.append(f)
        return new

    def __rshift__(self, v):
        new = deepcopy(self)
        new.args = v
        return new

    def call_logic(self, *args):
        for f in self.stack:
            if type(args) is tuple:
                args = f(*args)
            else:
                args = f(args)
        return args

    def __call__(self, *args):
        if 'args' in self.__dict__:
            return self.call_logic(self.args)
        else:
            return self.call_logic(*args)


自然,这是一个很大的拐杖,即使没有杂物也很有趣,尽管在类似情况下它并不那么重要。



pipe = CreatePipeline()
powered_sum = pipe | str | list | (lambda l: map(lambda x: int(x), l)) | enumerate | (lambda e: [v**(i+1) for i,v in e]) | sum


, , , , , .





( ):



def f_partitial (x,y,z):
    return x+y+z
v = f_partial(1,2)
# type(v) = -    f_partial,  : ['z']
print(v(3))
# 
print(f_partial(1,2,3))


( ). pipe :



powered_sum = pipe | str | list | map(lambda x: int(x)) | enumerate | (lambda e: [v**(i+1) for i,v in e]) | sum
# map       
# map(lambda x: int(x))()  


map(lambda x: int(x)) .

:



from inspect import getfullargspec
from copy import deepcopy

class CreatePartFunction:
    def __init__(self, f):
        self.f = f
        self.values = []

    def __call__(self, *args):
        args_f = getfullargspec(self.f)[0]
        if len(args) + len(self.values) < len(args_f):
            new = deepcopy(self)
            new.values = new.values + list(args)
            return new
        elif len(self.values) + len(args) == len(args_f):
            return self.f(*tuple(self.values + list(args)))


:



#     inspect   map
m = lambda f, l: map(f, l)
#        
pmap = CreatePartFunction(m)
powered_sum = pipe | str | list | pmap(lambda x: int(x)) | enumerate | (lambda e: [v**(i+1) for i,v in e]) | sum


( ), , , , :



def f (x,y,z):
    return x+y+z
f = CreatePartFunction(f)
# 
print(f(1,2,3))
# 
print(f(1,2)(3))
print(f(1)(2,3))
#  
# 2(3) - int  callable
print(f(1)(2)(3))
# 
print((f(1)(2))(3))




, , , , , , , .




All Articles