Python is functional?!

Outline

  • Functional programming
  • First-class functions
  • Higher order functions
  • Nested functions
  • Real-life examples

Definition

WTFunctional programming?!

Functional programming is a paradigm that treats computation as the evaluation of mathematical functions and avoids shared and mutable data.
Programming is done with expressions or declarations instead of statements.
  • Well-defined and deterministic behavior
  • No side-effects
  • Focus on WHAT to do, not HOW to do it
⇨ Clear and concise code
⇨ Easy to run in parallel

Python is not functional

Bazinga

First class functions

Lambdas

Functions as variables


                        square = lambda x: x**2
                        
                        print(square) # <function <lambda> at 0x000002131C8E7BF8>
                        
                        print(square(2)) # 4
                    

Higher order functions

Map

Apply functions to all elements

Procedural


                            result = []
                            for x in data:
                              y = square(x)
                              result.append(y)
                        

Functional


                                result = map(square, data)
                            

Pythonic


                                result = [square(x) for x in data]
                            

Higher order functions

Filter

Keep or discard elements in a collection

Procedural


                            result = []
                            for x in data:
                              if is_even(x):
                                result.append(x))
                        

Functional


                                result = filter(is_even, data)
                            

Pythonic


                                result = [x for x in data if is_even(x)]
                            

Higher order functions

Reduce

Aggregate elements in a collection to produce a single result

Procedural


                            result = 0
                            for x in data:
                              result += x
                        

Functional


                            from functools import reduce

                            result = reduce(add, data, 0)
                        

Yo dawg

I heard you like functions

Nested functions

Return a function

Functions can be used as return value


                        def greeter():
                          return lambda: "Hello world"
                        
                        print(greeter) 
                        # <function greeter at 0x0000022A1FC99D08>
                        
                        print(greeter())
                        # <function greeter.<locals>.<lambda> at 0x0000022A1FC998C8>
                        
                        print(greeter()())
                        # Hello world
                    

Nested functions

Closure

Inner functions can use variables from parent function


                        def counter():
                          i = 0
                          def increment():
                            nonlocal i
                            i += 1
                            return i
                          return increment
                        
                        count = counter()
                        
                        print(count())  # 1
                        print(count())  # 2
                    

Nested functions

Currying

Inner functions can use parameters from parent function


                        def pow(exp):
                          return lambda x: x**exp
                        
                        square = pow(2)
                        
                        print(square(3)) # 9
                    

Now what?

map(fun, everywhere)!

Examples

Text classification: load documents


                        def load_documents(data_folder):
                          categories = os.listdir(data_folder)
                          
                          def list_document_paths(category):
                            cat_folder = path.join(data_folder, category)
                            file_paths = [path.join(cat_folder, f) for f in os.listdir(cat_folder)]
                            doc_paths = [f for f in file_paths if f.endswith(".txt")]
                            return doc_paths                    
                          
                          documents = [
                            InputDocument(document_path, category) 
                            for category in categories
                            for document_path in list_document_paths(category))
                          ]
                          return documents
                    

Examples

Text classification: training


                        def training(documents):
                          tokenized_docs = [tokenize(doc) for doc in documents]
                          preprocessed_docs = [preprocess(doc) for doc in tokenized_docs]
                          
                          vocabulary = build_vocabulary(preprocessed_docs)
                          build_bow = lambda doc: assign_weights(vocabulary, doc)
                          bow_docs = [build_bow(doc) for doc in preprocessed_docs]
                          
                          model = train_model(bow_docs)
                          return model, vocabulary
                    

So long

And thanks for all the attention