Das Hauptziel dieses Beitrags ist es, ein in Python wenig nützliches Architekturmuster zu zeigen, das als " funktionaler Kern - imperativer Wrapper " bezeichnet wird, bei dem funktionale Programmierung mit imperativer Programmierung gemischt wird, um die Mängel jedes einzelnen von ihnen zu beseitigen. Es ist bekannt, dass funktionale Sprachen bei der Interaktion mit der "realen Welt" schwach sind, z. B. Benutzereingaben, GUI-Interaktionen oder andere E / A.
Dieser Ansatz nutzt Pythons Fähigkeit, mit Funktionen innerhalb des Funktionsparadigmas zu arbeiten, bei denen Funktionen auf die gleiche Weise wie jedes andere Objekt bearbeitet werden können: als Argumente an andere Funktionen übergeben, von Funktionen zurückgegeben und in Sequenzen als deren Elemente enthalten.
Für diejenigen, die die funktionale Programmierung in Python auffrischen möchten, empfehle ich, dem Link zu meinem Beitrag über die Grundlagen von FP in Python zu folgen .
Der funktionale Programmierstil kommt dem Denken einer Person bei der Lösung eines Problems sehr nahe. „Lass es gegeben werden x
. Um das Problem mit diesen Daten zu lösen, müssen eine Reihe von Transformationen durchgeführt werden. Wenden Sie sich zuerst an sie an f
und erhalten Sie die resultierenden Daten x'
. Dann auf die neuen Daten anwenden f2
und neue resultierende Daten x''
usw. erhalten.
, . , .. . , . , (), .
, , (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. . , , , .