oo_vs_fp

Upload: dhanasekaran-anbalagan

Post on 06-Apr-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

  • 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