Object Orientation vs. Functional Programming: Writing Modular Python Programs
Object Orientation vs. Functional Programming: Writing Modular Python Programs
Functional Programming
Writing Modular Python Programs
About Me
Modularity
Roadmap
Thesis
Object Orientation is a proven way of creating models in software that represent the problem domain in a useful manner. There are many patterns that show how to achieve the modularity goal in different contexts.
Antithesis
Functional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make expressing reusable algorithms natural and customising them easy.
Synthesis
Python has good support for both styles of programming and for good reason. Depending on the situation one or the other maybe more appropriate. Moreover in Python these tools do not only exist but they complement each other.
Object Orientation
Class Oriented The Three Pillars of OO in Python: 1. Delegation 2. Polymorphism 3. Instantiation
Template Method
class Game(object): PLAYERS = 2 def initialize_game(self): raise NotImplementedError() def make_play(self, player): raise NotImplementedError() def end_of_game(self): raise NotImplementedError() def print_winner(self): print self.current def play_game(self, players=PLAYERS): self.initialize_game() self.current = 0 while not self.end_of_game(): self.make_play(self.current) self.current = (self.current + 1)\ % players self.print_winner() class Monopoly(Game): PLAYERS = 4 def initialize_game(self): pass # Monopoly code here def make_play(self, player): pass # Monopoly code here def end_of_game(self): pass # Monopoly code here def print_winner(self): pass # Monopoly code here class Chess(Game): def initialize_game(self): pass # Chess code here def make_play(self, player): pass # Chess code here def end_of_game(self): pass # Chess code here
Mixins
class XMPPClient(object): def connect(self): pass # XMPP code def disconnect(self): pass # XMPP code def send(self, player): pass # XMPP code def terminate(self, player): raise NotImplementedError() def mainain_presence(self): self.connect() while not self.terminate(): yield self.disconnect()
class OnlineChess (Game, XMPPClient): def initialize_game(self): pass # Chess code here
...
def end_of_game(self): pass # Chess code here def terminate(self, player): return self.end_of_game()
Wrapping/Composition
Prefer Composition over Inheritance Use a class's functionality but not its API Expose only limited part of an object Typical uses: Adapt Proxy Decorate
Wrapping/Composition
class Eprom(object): def read(self): pass # Eprom code def write(self, data): pass # Eprom code def complete(self): pass # Eprom code class FileLikeEprom(object): def __init__(self, eprom): self._eprom = eprom def read(self): return self._eprom.read() def write(self, data): self._eprom.write(data) def close(self): self._eprom.complete() class SafeEprom(object): def __init__(self, eprom): self._eprom = eprom def read(self): return self._eprom. read() def write(self, data): if safe(data): self._eprom.write (data) def close(self): self._eprom.complete()
Wrapping/Composition (Tricks)
Don't Repeat Yourself Avoid boilerplate Use __getattr__ to return computed attributes
class FileLikeEprom(object): def __init__(self, eprom): self._eprom = eprom def __getattr__(self, n): if n == 'close': return self.close else: return getattr(self._eprom, n) def close(self): self._eprom.complete()
Mixins Again
class SafeAndFileLike(FileLikeEprom, SafeEprom): def __init__(self, *args, **kwargs): return super(SafeAndFileLike, self).__init__(*args, **kwargs)
Roadmap
Thesis
Object Orientation is a proven way of creating models in software that represent the problem domain in a useful manner. There are many patterns that show how to achieve the modularity goal in different contexts.
Antithesis
Functional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make expressing reusable algorithms natural and customising them easy.
Synthesis
Python good support for both styles of programming and for good reason. Depending on the situation one or the other maybe more appropriate. Moreover in Python these tools do not only exist but they complement each other.
Functional Programming
Functions take input and produce output, without any side effects. Pure functional languages are strict about side effect freeness. Python is not a pure functional language. Functions may be internally imperative, but appear purely functional in their behaviour.
Callbacks
The Hollywood principle Role reversal, library code calls your code Library code accepts a callable and invokes it when appropriate The main uses: Customisation Event Handling
operator module
attrgetter itemgetter add mul pow ...
from operator import attrgetter class Person(object): def __init__(self, f, s): self.f = f self.s = s def __str__(self): return '%s %s' % (self.f, self. s) first_name = attrgetter('f') surname = attrgetter('s')
Operations on aggregates
map filter reduce sum
>>> def square(x): ... return x ** 2 ... >>> s = [1, 2, 3, 4, 5] >>> sum(map(square, s)) 55 >>> def odd(x): ... return x % 2 ... >>> s = [1, 2, 3, 4, 5] >>> sum(map(square, filter(odd, s))) 35
itertools module
cycle() repeat() chain() tee() product() ...
Decorators
def cache(fn, c=None): if c is None: c = {} def cached(*args): if args in c: return c[args] result = fn(*args) c[args] = result return result return cached def adder(x, y): return x + y adder = cache(adder) def cache(fn, c=None): if c is None: c = {} def cached(*args): if args in c: return c[args] result = fn(*args) c[args] = result return result return cached @cache def adder(x, y): return x + y
Roadmap
Thesis
Object Orientation is a proven way of creating models in software that represent the problem domain in a useful manner. There are many patterns that show how to achieve the modularity goal in different contexts.
Antithesis
Functional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make expressing reusable algorithms natural and customising them easy.
Synthesis
Python good support for both styles of programming and for good reason. Depending on the situation one or the other maybe more appropriate. Moreover in Python these tools do not only exist but they complement each other.
Unbound methods
>>> food = ['Spam', 'ham', 'Cheese', 'eggs'] >>> sorted(food) ['Cheese', 'Spam', 'eggs', 'ham'] >>> sorted(food, key=str.lower) ['Cheese', 'eggs', 'ham', 'Spam'] >>>
>>> sorted(food, key='ham'. lower) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: lower() takes no
Functions are descriptors Override binding behaviour Override differently for A.x and a.x Unbound methods know their class but not their instance Ideal for use in a functional style
Dependency Inversion
class Employee(object): def __init__(self, f, s): self.f = f self.s = s def register(self): pass # Register me def register(emps): for f, s in emps: emp = Employee(f, s) emp.register() >>> emps = [('John', 'Smith'), ('Mary', 'Doe')] >>>register(emps) def employee_fact(f, s): return Employee(f, s) def register(emps, fact): for f, s in emps: emp = fact(f, s) emp.register() >>> emps = [('John', 'Smith'), ('Mary', 'Doe')] >>>register(emps, employee_fact)
Roadmap
Thesis
Object Orientation is a proven way of creating models in software that represent the problem domain in a useful manner. There are many patterns that show how to achieve the modularity goal in different contexts.
Antithesis
Functional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make expressing reusable algorithms natural and customising them easy.
Synthesis
Python good support for both styles of programming and for good reason. Depending on the situation one or the other maybe more appropriate. Moreover in Python these tools do not only exist but they complement each other nicely.
We hire superheroes!
www.demonware.net/jobs/ Development & Operations Positions Come talk to us