Uma das principais vantagens do Python é sua expressividade. A funcionalidade da linguagem permite que você descreva de forma concisa as transformações nos dados. Em minha opinião, Python carece de algumas ferramentas que ajudariam a descrever as transformações de dados de forma mais conveniente e suplementar o componente funcional da linguagem, em particular, "pipelines de função" e sua aplicação parcial. Portanto, neste post eu despejo água sobre a possibilidade e necessidade desses fundos com experimentos para sua implementação. Eu vim de várias maneiras para receber críticas. Gostar de ler!
Resumidamente sobre FP em Python e por que não há pipelines suficientes, por exemplo
Python tem algumas ferramentas básicas muito úteis como map (), reduce (), filter (), funções lambda, iteradores e geradores. Aconselho a todos que não estão familiarizados com este artigo . Em geral, tudo isso permite que você descreva de forma rápida e natural as transformações em listas, tuplas e assim por diante. Muitas vezes (comigo e meus amigos pitonistas) o que aconteceone-liner- essencialmente um conjunto de transformações sequenciais, filtros, por exemplo:
Kata com CodeWars : Find
, ( ), .
:
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]
" ". .
( "|" — ):
# 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))
, , , , , , , .