Note: This article is inspired by a blog post “Embracing the Four Python Programming Styles” 1
Programming paradigm is a way to categorize programming languages by their features, and procedural, object oriented, functional, logic-based are common paradigms. Among those paradigms, there is always debates or curiosity of which is better than what2. Although you may not noticed, Python is very flexible on a programming style - you can code not only in the procedural or the objective oriented but also the functional style3. Due to this flexibility, it is highly likely that you are going to face the question of “What programming paradigm should I use?”. The short answer is “you are fine to use ANY style”. However, if you don’t want to mix match with only disadvantages of each paradigm, it would be nice to know characteristics of each style.
Procedural, one type of imperative language, is based on the procedure which can be any series of computational steps4. So basically, you combine these procedures to instruct a computer each step it has to take to perform a certain task. Procedures are usually modularized by a function definition which provides very simple interface to be used by others. In other words, programmers can easily combine modules from different places to create a program. However, since each function has no relationship with another, it can be placed anywhere, giving programmers a hard task to find the correct procedure (which may lead duplicated procedures all over the places). In order to solve this problem, programming languages usually provides a way to containerize related functions (and variables). In Python, each file behaves as a container (called as a module in Python) thus you can easily organize related items without difficulty.
Getting a sum of a list can be done in the procedural way as following:
new_lst = [1, 2, 3, 4] def sum_list(lst): result = 0 for value in lst: result += value return result print(sum_list(new_lst))
Object Oriented is one of the imperative languages as well, but it differs from procedural by providing a concept of “object”. As the name suggests, the object is a center of everything. This is the concept of an encapsulation which allows an instance (object) to contain all related data and behaviors (methods). By the encapsulation, the object oriented style allows related data and methods to be sticked together which is somewhat difficult for the procedure programming to achieve. Furthermore, the concept of an inheritance provides reusability of data and methods, thus programmer needs to define only once for all the common data/methods in order to support multiple classes (a frame to create objects). The main disadvantage of the object oriented paradigm is that a program can easily become a complex monster. Although the concept of this paradigm mimics a very familiar concept in our life (biological classification), categorizing everything into some type of classification can be very tricky and may increase a complexity of a program.
The same sum of a list procedure can be done in the object oriented way as follows:
class ListEvaluator: def __init__(self, lst): self.holding_list = lst def sum_list(self): result = 0 for value in self.holding_list: result += value self.list_sum = result evaluator = ListEvaluator([1, 2, 3, 4]) evaluator.sum_list() print(evaluator.list_sum)
A functional programming language is different from above two. It is classified as a declarative language which uses expressions or declarations rather than statements as in imperative languages. It mimics the mathematical function and avoids using changing states and mutable data 5. Since everything is immutable, it has no side effect (assuming that only the pure functional style is used). A program is said to have a side effect if the result of a function is affected by some factor that resides outside of that function6. For example, in the object oriented language, a method has a side effect if it depends on an instance’s attribute and that attribute can be altered by another methods in the instance. Having the side effect free characteristic allows functional programming more understandable and predictable. But, since the computer is designed and working more like the imperative paradigm (mutable states with statements), it is impossible to make a program only using the pure functional paradigm (at least the I/O or memory work cannot be done in the pure functional way). Furthermore, since imperative languages were used as the main stream paradigm for several decades, using a declarative language can be very tricky (in personal experience, different paradigm requires formatting the programmer’s brain and installing a new OS :P).
Functional style of getting a sum of a list:
new_lst = [1, 2, 3, 4] def sum_list(lst): # not so sure if len is defined in a functional way, but to give a general concept if len(lst) == 1: return lst else: return lst + sum_list(lst[1:]) print(sum_list(new_lst)) # or the pure functional way in python using higher order function import functools print(functools.reduce(lambda x, y: x + y, new_lst))
As you can see each programming paradigm has pros and cons. Furthermore, in my opinion, by designing the program architecture carefully, disadvantages of one paradigm can be overcome. In other words, you don’t have to worry about what paradigm would be better to program in Python (at least it supports most of paradigms you can use of). You can mix match several paradigms to code a single program, or it is completely fine to stick with one that is the most familiar to you. However, no matter which strategy you are applying, there are other things that are waaaay more important: 1. nice documentations, 2. codes with high readability and 3. pleasant communications to work efficiently with others who also program on the same code as yours.