OO_vs_FP
-
Upload
dhanasekaran-anbalagan -
Category
Documents
-
view
221 -
download
0
Transcript of OO_vs_FP
-
8/3/2019 OO_vs_FP
1/33
Object Orientationvs.
Functional ProgrammingWriting Modular Python Programs
Twitter: @insmallportions
www.insmallportions.com
-
8/3/2019 OO_vs_FP
2/33
About Me
-
8/3/2019 OO_vs_FP
3/33
Modularity
-
8/3/2019 OO_vs_FP
4/33
Roadmap
ThesisObject Orientation is a provenway of creating models insoftware that represent theproblem domain in a useful
manner. There are manypatterns that show how toachieve the modularity goal indifferent contexts.
AntithesisFunctional Programming is along standing approach todefining processes in terms ofothers at different levels of
abstraction. Higher orderfunctions make expressingreusable algorithms naturaland customising them easy.
SynthesisPython has good support for both styles of programming andfor good reason. Depending on the situation one or the othermaybe more appropriate. Moreover in Python these tools do
not only exist but they complement each other.
-
8/3/2019 OO_vs_FP
5/33
Object Orientation
Class Oriented The Three Pillars of
OO in Python:1. Delegation2. Polymorphism3. Instantiation
-
8/3/2019 OO_vs_FP
6/33
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
defplay_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)\
% playersself.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 heredef end_of_game(self):
pass # Chess code here
-
8/3/2019 OO_vs_FP
7/33
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 importMapping>>> class MyMapping(Mapping):... def __getitem__(self, key):... return 101
...>>> m = MyMapping()Traceback (most recent call last):File "", line 1, in
TypeError: Can't instantiate abstract
class MyMapping with abstractmethods __iter__, __len__
-
8/3/2019 OO_vs_FP
8/33
Mixins
class XMPPClient(object):def connect(self):
pass # XMPP codedef disconnect(self):
pass # XMPP codedef send(self, player):
pass # XMPP codedef terminate(self, player):
raise NotImplementedError()
def mainain_presence(self):
self.connect()while not self.terminate():
yieldself.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()
-
8/3/2019 OO_vs_FP
9/33
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
-
8/3/2019 OO_vs_FP
10/33
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
-
8/3/2019 OO_vs_FP
11/33
Wrapping/Compositionclass Eprom(object):
def read(self):
pass # Eprom codedef write(self, data):
pass # Eprom codedef complete(self):
pass # Eprom codeclass FileLikeEprom(object):def __init__(self, eprom):
self._eprom = epromdef 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 = epromdef read(self):
return self._eprom.read()
def write(self, data):if safe(data):
self._eprom.write(data)
def close(self):
self._eprom.complete()
-
8/3/2019 OO_vs_FP
12/33
Wrapping/Composition (Tricks)
class FileLikeEprom(object):def __init__(self, eprom):self._eprom = eprom
def __getattr__(self, n):if n == 'close':
return self.closeelse:
return getattr(self._eprom,n)
def close(self):self._eprom.complete()
Don't Repeat Yourself Avoid boilerplate Use__getattr__to
return computed
attributes
-
8/3/2019 OO_vs_FP
13/33
Mixins Again
class SafeAndFileLike(FileLikeEprom, SafeEprom):def __init__(self, *args, **kwargs):return super(SafeAndFileLike, self).__init__(*args,
**kwargs)
-
8/3/2019 OO_vs_FP
14/33
Roadmap
ThesisObject Orientation is a provenway of creating models insoftware that represent theproblem domain in a useful
manner. There are manypatterns that show how toachieve the modularity goal indifferent contexts.
AntithesisFunctional Programming is along standing approach todefining processes in terms ofothers at different levels of
abstraction. Higher orderfunctions make expressingreusable algorithms naturaland customising them easy.
SynthesisPython good support for both styles of programming and forgood reason. Depending on the situation one or the othermaybe more appropriate. Moreover in Python these tools do
not only exist but they complement each other.
-
8/3/2019 OO_vs_FP
15/33
Functional Programming
Functions take input andproduce output, withoutany side effects.
Pure functional languages
are strict about side effectfreeness.
Python is not a purefunctional language.
Functions may beinternally imperative, butappear purely functionalin their behaviour.
-
8/3/2019 OO_vs_FP
16/33
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
-
8/3/2019 OO_vs_FP
17/33
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 = fself.s = s
def __str__(self):
return '%s %s' % (self.f, self.s)def __eq__(self, other):
return self.s == other.sdef __lt__(self, other):
return self.s < other.s
-
8/3/2019 OO_vs_FP
18/33
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 = fself.s = s
def __str__(self):
return '%s %s' % (self.f, self.s)first_name = lambda p: p.fsurname = lambda p: p.s
-
8/3/2019 OO_vs_FP
19/33
operator module
from operator import attrgetter
class Person(object):def __init__(self, f, s):
self.f = f
self.s = sdef __str__(self):return '%s %s' % (self.f, self.
s)
first_name = attrgetter('f')surname = attrgetter('s')
attrgetter itemgetteraddmul
pow...
-
8/3/2019 OO_vs_FP
20/33
Operations on aggregates
map filter reducesum
>>> 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
-
8/3/2019 OO_vs_FP
21/33
itertools module
cycle() repeat() chain() tee()
product()...
-
8/3/2019 OO_vs_FP
22/33
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] = resultreturn 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] = resultreturn result
return cached
@cachedef adder(x, y):
return x + y
Do not write code like this, use: functools.lru_cache
-
8/3/2019 OO_vs_FP
23/33
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
-
8/3/2019 OO_vs_FP
24/33
Roadmap
Thesis
Object Orientation is a provenway of creating models insoftware that represent theproblem domain in a useful
manner. There are manypatterns that show how toachieve the modularity goal indifferent contexts.
Antithesis
Functional Programming is along standing approach todefining processes in terms ofothers at different levels of
abstraction. Higher orderfunctions make expressingreusable algorithms naturaland customising them easy.
SynthesisPython good support for both styles of programming and forgood reason. Depending on the situation one or the othermaybe more appropriate. Moreover in Python these tools do
not only exist but they complement each other.
-
8/3/2019 OO_vs_FP
25/33
Best of Both Worlds
-
8/3/2019 OO_vs_FP
26/33
Unbound methods
Functions are descriptors
Override bindingbehaviour
Override differently for A.xand a.x
Unbound methods knowtheir class but not theirinstance
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 "", line 1, in
TypeError: lower() takes noar uments 1 iven
-
8/3/2019 OO_vs_FP
27/33
Computed fields (property)
class Person(object):
def __init__(self, f, s):self.f = fself.s = s
@propertydef 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 = fself._s = s
@propertydef s(self):
return self._s.upper()@s.setterdef s(self, value):
self._s = value>>> p = Person('Jane','Doe')>>> p.s'DOE'
property([fget[, fset[, fdel[, doc]]]])
d h
-
8/3/2019 OO_vs_FP
28/33
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' %t, self.f, self.s)>>> c.fullname'Mr John Smith'
-
8/3/2019 OO_vs_FP
29/33
Dependency Inversion
class Employee(object):
def __init__(self, f, s):self.f = fself.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)
-
8/3/2019 OO_vs_FP
30/33
Python classes are factories
class Employee(object):
def __init__(self, f, s):self.f = fself.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 othercallables to the caller
Allows us to postpone thecreation of a factory until it isactually needed
M f ll bl
-
8/3/2019 OO_vs_FP
31/33
Many types of callables
Functions Unbound methods Bound methods Classes
Any object that has a
__call__method is acallable
Testable using thecallable built-in function
>>> callable(str)True>>> callable('Spam')False>>>
class Callable(object):def __init__(self, m):
self.message = mdef __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 "", line 1, in
TypeError: 'NotCallable' object is notcallable
-
8/3/2019 OO_vs_FP
32/33
Roadmap
Thesis
Object Orientation is a provenway of creating models insoftware that represent theproblem domain in a usefulmanner. There are manypatterns that show how toachieve the modularity goal indifferent contexts.
Antithesis
Functional Programming is along standing approach todefining processes in terms ofothers at different levels ofabstraction. Higher orderfunctions make expressingreusable algorithms naturaland customising them easy.
SynthesisPython good support for both styles of programming and forgood reason. Depending on the situation one or the othermaybe more appropriate. Moreover in Python these tools do notonly exist but they complement each other nicely.
-
8/3/2019 OO_vs_FP
33/33
We hire superheroes!
www.demonware.net/jobs/ Development & Operations
Positions Come talk to us