Inti fungsional sebagai pipa dengan Python

Tujuan utama dari posting ini adalah untuk menunjukkan satu pola arsitektur yang jarang digunakan dalam Python yang disebut " inti fungsional - pembungkus imperatif ", di mana pemrograman fungsional dicampur dengan pemrograman imperatif dalam upaya untuk meniadakan kekurangan masing-masing. Bahasa fungsional diketahui lemah saat berinteraksi dengan "dunia nyata", seperti input pengguna, interaksi GUI, atau I / O lainnya.





Pendekatan ini menggunakan kemampuan Python untuk bekerja dengan fungsi dalam paradigma fungsional, di mana fungsi dapat dimanipulasi dengan cara yang sama seperti objek lainnya: diteruskan sebagai argumen ke fungsi lain, dikembalikan dari fungsi, dan disertakan dalam urutan sebagai elemennya.





Bagi mereka yang ingin mempelajari pemrograman fungsional dengan Python, saya sarankan mengikuti tautan ke posting saya tentang dasar-dasar FP dengan Python.





Pipeline pemrosesan data
Pipeline pemrosesan data

Gaya pemrograman fungsional sangat mirip dengan bagaimana seseorang berpikir sambil memecahkan masalah. β€œBiarlah diberikan x



. Untuk menyelesaikan masalah dengan data ini, perlu dilakukan serangkaian transformasi. Pertama, terapkan ke mereka f



dan dapatkan data yang dihasilkan x'



. Kemudian terapkan ke data baru f2



dan dapatkan data baru yang dihasilkan x''



, dll.





, . , .. . , . , (), .





, , (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. , . ,





  • PyCon .





  • , .





  • Youtube Β« Python - Β».





, , Python , map/filter/reduce/zip functools. . , , , .








All Articles