4.12.2.1 - Higher-order functions, map, filter and fold (Python)

4.12.2.1 - Higher-order functions, map, filter and fold (Python)

Build simple functional transformations using functions as arguments and results. Learn how map changes every element, filter selects elements, and a seeded fold combines them into one result without changing the source list.

Higher-order functions and functional transformations

A functional program describes how values flow through functions, which allows transformations to be combined without relying on changing shared state.

Higher-order function

A function is higher-order if it accepts a function as an argument, returns a function as a result, or does both.

An ordinary function such as square receives a number and returns a number. A function such as apply_once(function, value) is higher-order because one argument is a function. A factory such as a curried add function is higher-order because its result is a function. Calling another named function internally is not enough on its own: the higher-order property concerns the function's arguments or result.

Pure functions return results determined by their inputs and do not cause side effects such as changing a global value or modifying a supplied list. This makes each transformation easier to reason about and test independently. Printing is an output side effect; our small programs keep printing at the outer boundary so the transformation functions themselves can remain pure.

Python supports several paradigms, including functional style. Its lists are mutable, so using Python does not automatically make a transformation pure. Instead, our functions return new lists or scalar results, leaving the original list alone. Local names such as selected can hold a new value without modifying the input data. Haskell, Standard ML, Scheme and Lisp are examples of languages supporting functional programming; Python is a suitable language for the functional experience required here.

Map, filter and fold are higher-order because a supplied function determines their operation. Their general roles are different:

OperationSupplied functionResult
mapElement transformationOne transformed result per input element
filterBoolean predicateExactly the original elements satisfying the condition
fold/reduceCombining functionOne accumulated result

Map transforms every element

Map applies a supplied transformation to every element, retaining the input order and the number of elements.

For a function f:A→Bf:A\to B, mapping f over a list of A values gives a list of B values. The element type may change: mapping length over strings produces integers. In functional notation, map square [2,3,4] produces [4,9,16]. This notation describes an operation; it is not a Python expression.

In Python 3, map(function, values) returns an iterator. Wrap it in list(...) when a concrete list is wanted. This is a language-interface detail: the underlying functional operation still supplies one result for every input. Applying map to an empty list yields no elements, so the materialised result is [].

Map a transformation over a list

{"code":"def square(value):\n return value * value\n\nvalues = [1, -2, 3]\nresults = list(map(square, values))\nprint(results)\nprint(values)\nprint(list(map(square, [])))\n","instructions":"Predict all three lines and run. Change square into a cube function, updating its name and both map calls. Predict and run again. Check that the original values list stays unchanged and that the empty input still produces an empty list.","files":[],"original_filename":"main.py","runtime_profile":"python-console-v1","file_mode":"fresh"}

The supplied argument is square, a function value, rather than square(values). Map handles applying it to each separate element. A call such as map(square(2), values) would instead supply the integer 4 where a function is needed.

Filter selects original elements

Filter retains the original elements for which a supplied predicate returns true, rather than replacing them with the predicate's Boolean results.

A predicate is a function returning a Boolean value. In functional notation, filter positive [-2,0,3,3], where positive n = n>0, gives [3,3]. The two occurrences of 3 remain in order. Mapping the same predicate would instead give [False,False,True,True]; that answers a different question.

Continue this lesson.

You’re previewing NovaLearn without an account. Create a free account to read the rest.

Create free account