Functional programming is a paradigm where the program is mainly an evaluation of (mathematical) functions, and is not through a series of defined steps that change the state of the program. Purely functional programs avoid the change of state (side effects) and mutable data. In Python, functional programming is realized through the use of complex expressions and declarations of functions.
One of the best ways to better understand the general concept of functional programming is through familiarizing yourself with the basic terms of functional programming:
- Side-effects: A function is said to have a side-effect if it modifies the state outside of its local environment. In other words, a side-effect is any observable change outside of the function scope that happens as a result of a function call. An example of such side-effects could be the modification of a global variable, the modification of an attribute or object that is available outside of the function scope, or saving data to some external service. Side-effects are the core of the concept of object-oriented programming, where class instances are objects that are used to encapsulate the state of application, and methods are functions bound to those objects that are supposed to manipulate the state of these objects.
- Referential transparency: When a function or expression is referentially transparent, it can be replaced with the value that corresponds to its inputs without changing the behavior of the program. So, a lack of side effects is a requirement for referential transparency, but not every function that lacks side-effects is a referentially transparent function. For instance, Python's built-in pow(x, y) function is referentially transparent, because it lacks side effects, and for every x and y argument, it can be replaced with the value of xy. On the other hand, the datetime.now() constructor method of the datetime type does not seem to have observable side-effects, but will return a different value every time it is called. So, it is referentially opaque.
- Pure functions: A pure function is a function that does not have any side-effects and which always returns the same value for the same set of input arguments. In other words, it is a function that is referentially transparent. Every mathematical function is, by definition, a pure function.
- First-class functions: Language is said to contain first-class functions if functions in this language can be treated as any other value or entity. First-class functions can be passed as arguments to other functions, returned as function return values, and assigned to variables. In other words, a language that has first-class functions is a language that treats functions as first-class citizens. Functions in Python are first-class functions.
Using these concepts, we could describe a purely functional language as a language that has first-class functions that is concerned only with pure functions, and avoids any state modification and side-effects. Python, of course, is not a purely functional programming language, and it would be really hard to imagine a useful Python program that uses only pure functions without any side-effects. Python offers a large variety of features that, for years, were only accessible in purely functional languages, so it is possible to write substantial amounts of code in a functional way, even though Python isn't functional by itself.
Let's take a look at Lambda functions in the next section.