17.1. OOP About
Three main programing paradigms
Programming paradigms
Procedural Programming (PP)
Functional Programming (FP)
Object Oriented Programming (OOP)
17.1.1. Procedural Programming
Languages: C, Pascal, Fortran, COBOL, BASIC, etc.
Share: 20% (don't quote me on that)
Since: 1950s
Vocabulary: variable, constant, reference, procedure, call, loop, iterate, switch, module, subprogram
Scaling: Vertical (buy faster computer)
Procedure is a set of commands which can be executed in order
Procedures == routines == subroutines
Function can return, procedures can't
Function has read only access to its parameters, and produce no side-effects
Procedure might have write access to its parameters, and are expected to produce side-effects
>>> def is_even(x):
... if x % 2 == 0:
... return True
... else:
... return False
>>>
>>> result = []
>>> for x in range(0,5):
... if is_even(x):
... result.append(x)
...
>>> print(result)
[0, 2, 4]
17.1.2. Functional Programming
Languages: OCaml, Haskel, Scheme, Lisp, Closure, etc.
Share: 5% (don't quote me on that)
Since: 1930s
Initiator: Alonso Church, lambda calculus, 1930s
Scaling: Horizontal (add more computers to the cluster)
Vocabulary: lambda, closure, curry, pure function, atom, bridge, monad, monoid, map, filter, reduce
No loops, use map, filter, recurrence
No variables, only constant values
For instance, a function sort might take a list, and return a new sorted list; whereas a procedure sort might take a list, and modify that list in-place without returning a new list.
>>> from functools import reduce
>>> from operator import add
>>>
>>>
>>> def even(x):
... return x % 2 == 0
>>>
>>> def positive(x):
... return x > 0
>>>
>>> def non_negative(x):
... return x >= 0
>>>
>>> def square(x):
... return x ** 2
>>>
>>> def increment(x):
... return x + 1
>>>
>>> def decrement(x):
... return x - 1
>>>
>>> def apply(data, fn):
... return map(fn, data)
>>>
>>> filters = (
... even,
... positive,
... non_negative,
... )
>>>
>>> maps = (
... square,
... increment,
... decrement,
... )
>>>
>>> data = range(0, 1024)
>>> filtered = reduce(apply, filters, data)
>>> mapped = reduce(apply, maps, filtered)
>>> result = reduce(add, mapped)
>>>
>>> result
1024
17.1.3. Object Oriented Programming
Languages: Python, Java, JavaScript, C++, C#, Smalltalk, Swift
Share: 75% (don't quote me on that)
Since: 1970s
Vocabulary: class, instance, method, attribute, inheritance, subclass, superclass
Scaling: Vertical (buy faster computer)
>>> class User:
... def __init__(self, firstname, lastname):
... self.firstname = firstname
... self.lastname = lastname
... self.authenticated = False
...
... def login(self, username, password):
... if username == 'alice' and password == 'secret':
... self.authenticated = True
... print('User logged-in')
... else:
... raise PermissionError('Invalid username or password')
...
... def logout(self):
... self.authenticated = False
... print('User logged-out')
...
... def set_name(self, firstname, lastname):
... if self.authenticated:
... self.firstname = firstname
... self.lastname = lastname
... print('User name changed')
... else:
... raise PermissionError('User is not authenticated')
>>> user = User('Alice', 'Apricot')
>>>
>>> vars(user)
{'firstname': 'Alice', 'lastname': 'Apricot', 'authenticated': False}
>>> user.set_name('Bob', 'Banana')
Traceback (most recent call last):
PermissionError: User is not authenticated
>>> user.login('alice', 'secret')
User logged-in
>>>
>>> vars(user)
{'firstname': 'Alice', 'lastname': 'Apricot', 'authenticated': True}
>>> user.set_name('Bob', 'Banana')
User name changed
>>>
>>> vars(user)
{'firstname': 'Bob', 'lastname': 'Banana', 'authenticated': True}
>>> user.logout()
User logged-out
>>>
>>> vars(user)
{'firstname': 'Bob', 'lastname': 'Banana', 'authenticated': False}
17.1.4. Philosophy
keyword is defined by parser:
class
type is defined by class keyword and label:
>>> class str:
... def __init__(self, value):
... ...
instance is created from type and scalar:
>>> str('alice')
>>> str('secret')
value is created from instance and identifier:
>>> username = str('alice')
>>> password = str('secret')
sequence is created from multiple values:
>>> user = str('alice'), str('secret')
mapping is created from sequence and labels:
>>> user = {
... 'username': str('alice'),
... 'password': str('secret'),
... }
data is created from mapping and behavior:
>>> class User:
... def __init__(self, username, password):
... self.username = username
... self.password = password
...
... def change_password(self, new_password):
... self.password = new_password
>>>
>>>
>>> user = User(
... username=str('alice'),
... password=str('secret'),
... )
>>>
>>> user.change_password(str('qwerty'))
program is created from data and business logic:
>>> class User:
... def __init__(self, username, password):
... self.username = username
... self.password = password
... self.authenticated = False
...
... def login(self):
... if not self.username or not self.password:
... raise PermissionError('Invalid username and/or password')
... print('User logged-in')
... self.authenticated = True
...
... def logout(self):
... self.authenticated = False
... print('User logged-out')
>>>
>>>
>>> user = User(
... username=str('alice'),
... password=str('secret'),
... )
>>>
>>> user.login()
User logged-in
>>>
>>> user.logout()
User logged-out