Pipelines y aplicación parcial de funciones, ¿por qué está en Python?



Una de las principales ventajas de Python es su expresividad. La funcionalidad del lenguaje le permite describir de manera concisa las transformaciones sobre los datos. En mi opinión, Python carece de algunas herramientas que ayudarían a describir las transformaciones de datos de manera más conveniente y complementar el componente funcional del lenguaje, en particular, las "canalizaciones de funciones" y su aplicación parcial. Por eso, en este post echo agua sobre la posibilidad y necesidad de estos fondos con experimentos para su implementación. Vine de muchas maneras para recibir críticas. ¡Disfruta leyendo!



Brevemente sobre FP en Python y por qué no hay suficientes canalizaciones, por ejemplo



Python tiene algunas herramientas básicas bastante útiles como map (), reduce (), filter (), funciones lambda, iteradores y generadores. Aconsejo a todos los que no estén familiarizados con este artículo . En general, todo le permite describir rápida y naturalmente transformaciones en listas, tuplas, etc. Muy a menudo (conmigo y mis amigos pitonistas) lo que sucedeun trazador de líneas- esencialmente un conjunto de transformaciones secuenciales, filtros, por ejemplo:

Kata con CodeWars : Find



norte[un,segundo]:norte=0lminorte(norte)norteyoyo, norteyo - i-ésimo bit del número n



La tarea es bastante simple, desafortunadamente (pero afortunadamente para esta publicación), no hay mejores soluciones que las de frente.



Mi decisión:



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]


Usando los medios de FP tal como están, obtenemos un infierno entre paréntesis "de adentro hacia afuera". El oleoducto podría arreglar eso.



Canalizaciones de funciones



Por sim me refiero en el caso ideal (el operador "|" es preferencia personal):



# 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 . , ( ):



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)


, , , kwargs, .



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