object orientation vs functional programming in python
DESCRIPTION
TRANSCRIPT
![Page 1: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/1.jpg)
Object Orientationvs.
Functional Programming
Writing Modular Python Programs
Twitter: @insmallportionswww.insmallportions.com
![Page 2: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/2.jpg)
About Me
![Page 3: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/3.jpg)
Modularity
![Page 4: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/4.jpg)
RoadmapThesisObject 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.
AntithesisFunctional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make the idiomatic ways to perform certain tasks fall out naturally.
SynthesisPython 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.
![Page 5: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/5.jpg)
Object Orientation
● Class Oriented ● The Three Pillars of
OO are:1. Delegation2. Polymorphism3. Instantiation
![Page 6: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/6.jpg)
Template Methodclass 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
![Page 7: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/7.jpg)
Abstract Base Classes
>>> class MyDict(dict):... def __getitem__(self, key):... return 101... >>> d = MyDict()>>> d['x']101>>> d.get('x', 202)202>>>
>>> from collections import Mapping>>> class >>> from collections import Mapping>>> class MyMapping(Mapping):... def __getitem__(self, key):... return 101... >>> m = MyMapping()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: Can't instantiate abstract class MyMapping with abstract methods __iter__, __len__
![Page 8: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/8.jpg)
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()
![Page 9: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/9.jpg)
Mixins (Multiple Inheritance)
class A(object): pass
class B(A): def method1(self): pass
class C(A): def method1(self): pass class D(B, C): pass
![Page 10: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/10.jpg)
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
![Page 11: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/11.jpg)
Wrapping/Compositionclass 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 data.safe(): self._eprom.write(data) def close(self): self._eprom.complete()
![Page 12: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/12.jpg)
Wrapping/Composition (Tricks)
class FileLikeEprom(object): def __init__(self, eprom): self._eprom = eprom def __getattr__(self, a): if a == 'close': return self.close else: return getattr(self._eprom, a) def close(self): self._eprom.complete()
● Don't Repeat Yourself● Avoid boilerplate● Use __getattr__ to
return computed attributes
![Page 13: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/13.jpg)
Mixins Again
class SafeAndFileLike(FileLikeEprom, SafeEprom): def __init__(self, *args, **kwargs): return super(SafeAndFileLike, self).__init__(*args, **kwargs)
![Page 14: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/14.jpg)
RoadmapThesisObject 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.
AntithesisFunctional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make the idiomatic ways to perform certain tasks fall out naturally.
SynthesisPython 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.
![Page 15: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/15.jpg)
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.
![Page 16: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/16.jpg)
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
![Page 17: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/17.jpg)
sorted() sans Callbacks>>> people = [Person('John', 'Smith'),... Person('Mary', 'Doe'),... Person('Lucy', 'Pearl'),]>>> for p in sorted(people):... print p... Mary DoeLucy PearlJohn Smith>>>
class Person(object): def __init__(self, f, s): self.f = f self.s = s def __str__(self): return '%s %s' % (self.f, self.s) def __eq__(self, other): return self.s == other.s def __lt__(self, other): return self.s < other.s
![Page 18: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/18.jpg)
sorted() with Callbacks>>> for p in sorted(people, key=first_name):... print p... John SmithLucy PearlMary Doe>>> for p in sorted(people, key=surname_name):... print p... Mary DoeLucy PearlJohn Smith>>>
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 = lambda p: p.fsurname = lambda p: p.s
![Page 19: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/19.jpg)
operator module
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')
● attrgetter● itemgetter● add● mul● pow
![Page 20: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/20.jpg)
Operations on collections of objects
● sum● filter● map● reduce
>>> def square(x):... return x ** 2... >>> l = [1, 2, 3, 4, 5]>>> sum(map(square, l))55>>> def square(x):... return x ** 2...>>> def odd(x):... return x % 2...>>> l = [1, 2, 3, 4, 5]>>> sum(map(square, filter(odd, l)))35
![Page 21: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/21.jpg)
itertools module
● cycle()● repeat()● chain()● tee()● product()● and many more...
![Page 22: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/22.jpg)
Decoratorsdef 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
@cachedef adder(x, y): return x + y
Do not write code like this, use: functools.lru_cache
![Page 23: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/23.jpg)
Partial function evaluation
>>> from functools import partial>>> >>> def power(base, exp=1):... return base ** exp... >>> square = partial(power, exp=2)>>> cube = partial(power, exp=3)>>> >>> l = [1, 2, 3, 4, 5]>>> sum(map(square, l))55>>> print sum(map(cube, l))225
![Page 24: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/24.jpg)
RoadmapThesisObject 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.
AntithesisFunctional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make the idiomatic ways to perform certain tasks fall out naturally.
SynthesisPython 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.
![Page 25: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/25.jpg)
Best of Both Worlds
![Page 26: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/26.jpg)
Unbound methods
● 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
>>> 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 arguments (1 given)
![Page 27: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/27.jpg)
Computed fields (property)
class Person(object): def __init__(self, f, s): self.f = f self.s = s @property def fullname(self): return '%s %s' % (self.f, self.s) >>> p = Person('John', 'Smith')>>> p.fullname'John Smith'
class Person(object): def __init__(self, f, s): self.f = f self._s = s @property def s(self): return self._s.upper() @s.setter def s(self, value): self._s = value >>> p = Person('Jane', 'Doe')>>> p.s'DOE'
property([fget[, fset[, fdel[, doc]]]])
![Page 28: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/28.jpg)
property and inheritanceclass Person(object): def __init__(self, t, f, s): ... def full(self): return '%s %s' % (self.f, self.s) fullname = property(full)
class Customer(Person): def full(self): return '%s. %s %s' % (self.t, self.f, self.s) >>> c = Customer('Mr', 'John', 'Smith')>>> c.fullname'John Smith'
class Person(object): def __init__(self, t, f, s): ... def full(self): return '%s %s' % (self.f, self.s) def _full(self): return self.full() fullname = property(_full) class Customer(Person): def full(self): return '%s. %s %s' % (self.t, self.f, self.s) >>> c.fullname'Mr John Smith'
![Page 29: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/29.jpg)
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)
![Page 30: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/30.jpg)
Python classes are factories
class Employee(object): def __init__(self, f, s): self.f = f self.s = s def register(self): pass # Register me
def register(emps, fact): for f, s in emps: emp = fact(f, s) emp.register()
>>> emps = [('John', 'Smith'), ('Mary', 'Doe')]>>>register(emps, Employee)
● Python classes are callables● Indistinguishable from other
callables to the caller● Allow us to postpone the
creation of a factory until it actually needed
![Page 31: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/31.jpg)
Many types of callables
● Functions● Unbound methods● Bound methods● Classes
● Any object that has a __call__ method is a callable
● Testable using the callable built-in function
>>> callable(str)True>>> callable('Spam')False>>>
class Callable(object): def __init__(self, m): self.message = m def __call__(self): print self.messageclass NotCallable(object): def call(self): print "You Rang?"
>>> c = Callable('You Rang')>>> c()You Rang>>> n = NotCallable()>>> n()Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'NotCallable' object is not callable
![Page 32: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/32.jpg)
RoadmapThesisObject 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.
AntithesisFunctional Programming is a long standing approach to defining processes in terms of others at different levels of abstraction. Higher order functions make the idiomatic ways to perform certain tasks fall out naturally.
SynthesisPython 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.
![Page 33: Object Orientation vs Functional Programming in Python](https://reader034.vdocuments.mx/reader034/viewer/2022042521/54813f9ab37959582b8b5d62/html5/thumbnails/33.jpg)
We hire superheroes!
● www.demonware.net/jobs/ ● Development & Operations
Positions ● Come talk to me any time
or meet me at the hiring event