El objetivo principal de esta publicación es mostrar un patrón de arquitectura de poco uso en Python llamado " núcleo funcional - envoltorio imperativo ", en el que la programación funcional se mezcla con la programación imperativa en un intento de negar las deficiencias de cada uno de ellos. Se sabe que los lenguajes funcionales son débiles cuando interactúan con el "mundo real", como la entrada del usuario, la interacción de la GUI u otras E / S.
Este enfoque utiliza la capacidad de Python para trabajar con funciones dentro del paradigma funcional, en el que las funciones pueden manipularse de la misma manera que cualquier otro objeto: pasarse como argumentos a otras funciones, devolverse de funciones e incluirse en secuencias como sus elementos.
Para aquellos que buscan repasar la programación funcional en Python, recomiendo seguir el enlace a mi publicación sobre los conceptos básicos de FP en Python.
El estilo funcional de la programación está muy cerca de cómo piensa una persona mientras resuelve un problema. “Que se dé x
. Para solucionar el problema con estos datos, es necesario realizar una serie de transformaciones. Primero, aplíqueles f
y obtenga los datos resultantes x'
. Luego aplique a los nuevos datos f2
y obtenga nuevos datos resultantes x''
, etc.
, . , .. . , . , (), .
, , (1) (2) , debug, (3) , .
, . F#:
2
|> ( fun x -> x + 5)
|> ( fun x -> x * x)
|> ( fun x -> x.ToString() )
, 2, -. Python, , , , :
#
def pipe(data, *fseq):
for fn in fseq:
data = fn(data)
return data
Python:
pipe(2,
lambda x: x + 5,
lambda x: x * x,
lambda x: str(x))
:
add = lambda x: lambda y: x + y
square = lambda x: x * x
tostring = lambda x: str(x)
pipe(2,
add(5),
square,
tostring)
2 , '49'
. reduce
, , pipe .
pipe
: data
fseq
. for
. , data . .. , . pipe . .
. pipe *
. *
.
, , . ,
def my_sum(*args): #
return sum(args)
my_sum(1, 2, 3, 4, 5)
. ,
def fun(a, b, c, d):
print(a, b, c, d)
my_list = [1, 2, 3, 4]
fun(*my_list) #
class Factory:
def process(self, input):
raise NotImplementedError
class Extract(Factory):
def process(self, input):
print(" ...")
output = {}
return output
class Parse(Factory):
def process(self, input):
print(" ...")
output = {}
return output
class Load(Factory):
def process(self, input):
print(" ...")
output = {}
return output
pipe = {
"" : Extract(),
"" : Parse(),
"" : Load(),
}
inputs = {}
#
for name, instance in pipe.items():
inputs = instance.process(inputs)
:
... ... ...
for
, . - , . « , , , » - , - Erlang.
, , , .
(factorial
) (factorial_rec
). . , . .
, , - ;-), .. .
#
#
def main():
# ( c )
pipe(int(input(' : ')),
lambda n: (n, reduce(lambda x, y: x * y, range(1, n + 1))),
lambda tup:
print(f' {tup[0]} {tup[1]}'))
#
main()
:
: 4 (Enter)
4 24
- , .
, .. - - . . .
#
#
def get_int(msg=''):
return int(input(msg))
def main():
# 1.
def factorial_rec(n):
fn = lambda n, acc=1: acc if n == 0 else fn(n - 1, acc * n)
return n, fn(n)
# 2.
def factorial(n):
return n, reduce(lambda x, y: x * y, range(1, n + 1))
#
def indata():
def validate(n): #
if not isinstance(n, int):
raise TypeError(" .")
if not n >= 0:
raise ValueError(" >= 0.")
return n
msg = ' : '
return pipe(get_int(msg), validate)
#
def outdata():
def fn(data):
n, fact = data
print(f' {n} {fact}')
return fn
# ( )
pipe(indata(), # : - : int
factorial, # : int :
outdata()) # : : -
#
main()
:
: 4 (Enter)
4 24
:
pipe(indata(), factorial, outdata())
, .. indata
, factorial
outdata
. indata
, . factorial
, , , . outdata
. , indata , .
. -, - . -, .
:
. ,
factorial
,factorial_rec
.
pipe(indata(), factorial_rec, outdata())
, .
, – . debug
:
def debug(data):
print(data)
return data
, :
pipe(indata(), debug, factorial, debug, outdata())
, :
:
: 4 (Enter)
4
(4, 24)
4 24
, factorial
4
, (4, 24)
. , , . , debug
-, .
.
#
#
def main():
#
def fibonacci(n, x=0, y=1):
# fib n- .
fib = lambda n, x=0, y=1: x if n <= 0 else fib(n - 1, y, x + y)
# reduce acc
acc = []
reduce(lambda _, y: acc.append(fib(y)), range(n + 1))
return n, acc
#
def validate(n):
if not isinstance(n, int):
raise TypeError(" .")
if not n >= 0:
raise ValueError(" .")
if n > 10:
raise ValueError(" 10.")
return n
#
def indata():
msg = ' 10: '
return pipe(get_int(msg), validate)
#
def outdata():
def fn(data):
n, seq = data
msg = f' {n} :'
print(msg)
[print(el) for el in seq]
return fn
# ( )
pipe(indata(), fibonacci, outdata())
# .
main()
10: 10 (Enter)
10 :
1
1
2
3
5
8
13
21
34
55
#
#
#
def main():
#
def range_sum(data):
seq, params = data
fn = lambda start, end: 0 if start > end \
else seq[start] + fn(start + 1, end)
return fn(*params)
#
def indata():
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
params = (2,5) # params - start, end
return seq, params
#
def outdata():
def f(data):
msg = ' 2 5 '
print(msg, format(data), sep='')
return f
# ( )
pipe(indata(), range_sum, outdata())
# .
main()
2 5 18
Python . : . . , , , , , . , .)
Github. Strating Out with Python. , . ,
-
-
Youtube « Python - ».
, , Python , map/filter/reduce/zip functools. . , , , .