Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Object Orientation vs Functional Programming in Python

6,327 views

Published on

Object Orientation vs Functional Programming in Python

  1. 1. Object Orientation vs. Functional Programming Writing Modular Python ProgramsTwitter: @insmallportionswww.insmallportions.com
  2. 2. About Me
  3. 3. Modularity
  4. 4. RoadmapThesis AntithesisObject Orientation is a proven Functional Programming is away of creating models in long standing approach tosoftware that represent the defining processes in terms ofproblem domain in a useful others at different levels ofmanner. There are many abstraction. Higher orderpatterns that show how to functions make the idiomaticachieve the modularity goal in ways to perform certain tasksdifferent contexts. fall out naturally. 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 donot only exist but they complement each other.
  5. 5. Object Orientation● Class Oriented● The Three Pillars of OO are:1. Delegation2. Polymorphism3. Instantiation
  6. 6. Template Methodclass Game(object): class Monopoly(Game): PLAYERS = 2 PLAYERS = 4 def initialize_game(self): def initialize_game(self): raise NotImplementedError() pass # Monopoly code here def make_play(self, player): def make_play(self, player): raise NotImplementedError() pass # Monopoly code here def end_of_game(self): def end_of_game(self): raise NotImplementedError() pass # Monopoly code here def print_winner(self): def print_winner(self): print self.current pass # Monopoly code here def play_game(self, players=PLAYERS): class Chess(Game): self.initialize_game() def initialize_game(self): self.current = 0 pass # Chess code here while not self.end_of_game(): def make_play(self, player): self.make_play(self.current) pass # Chess code here self.current = (self.current + 1) def end_of_game(self): % players pass # Chess code here self.print_winner()
  7. 7. Abstract Base Classes>>> class MyDict(dict): >>> from collections import Mapping... def __getitem__(self, key): >>> class >>> from collections import... return 101 Mapping... >>> class MyMapping(Mapping):>>> d = MyDict() ... def __getitem__(self, key):>>> d[x] ... return 101101 ...>>> d.get(x, 202) >>> m = MyMapping()202 Traceback (most recent call last):>>> File "<stdin>", line 1, in <module> TypeError: Cant instantiate abstract class MyMapping with abstract methods __iter__, __len__
  8. 8. Mixinsclass XMPPClient(object): class OnlineChess def connect(self): (Game, XMPPClient): pass # XMPP code def initialize_game(self): def disconnect(self): pass # Chess code here pass # XMPP code def send(self, player): ... pass # XMPP code def end_of_game(self): def terminate(self, player): pass # Chess code here raise NotImplementedError() def terminate(self, player): def mainain_presence(self): return self.end_of_game() self.connect() while not self.terminate(): yield self.disconnect()
  9. 9. Mixins (Multiple Inheritance)class A(object): passclass B(A): def method1(self): passclass C(A): def method1(self): passclass D(B, C): pass
  10. 10. Wrapping/Composition● Prefer Composition over Inheritance● Use a classs functionality but not its API● Expose only limited part of an object● Typical uses: ○ Adapt ○ Proxy ○ Decorate
  11. 11. Wrapping/Compositionclass Eprom(object): class SafeEprom(object): def read(self): def __init__(self, eprom): pass # Eprom code self._eprom = eprom def write(self, data): def read(self): pass # Eprom code return self._eprom. def complete(self): read() pass # Eprom code def write(self, data): if data.safe():class FileLikeEprom(object): self._eprom.write def __init__(self, eprom): (data) self._eprom = eprom def close(self): def read(self): self._eprom.complete() return self._eprom.read() def write(self, data): self._eprom.write(data) def close(self): self._eprom.complete()
  12. 12. Wrapping/Composition (Tricks)● Dont Repeat Yourself class FileLikeEprom(object): def __init__(self, eprom):● Avoid boilerplate self._eprom = eprom● Use __getattr__ to def __getattr__(self, a): return computed if a == close: attributes return self.close else: return getattr(self._eprom, a) def close(self): self._eprom.complete()
  13. 13. Mixins Againclass SafeAndFileLike(FileLikeEprom, SafeEprom): def __init__(self, *args, **kwargs): return super(SafeAndFileLike, self).__init__(*args,**kwargs)
  14. 14. RoadmapThesis AntithesisObject Orientation is a proven Functional Programming is away of creating models in long standing approach tosoftware that represent the defining processes in terms ofproblem domain in a useful others at different levels ofmanner. There are many abstraction. Higher orderpatterns that show how to functions make the idiomaticachieve the modularity goal in ways to perform certain tasksdifferent contexts. fall out naturally. 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 donot only exist but they complement each other.
  15. 15. 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.
  16. 16. 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
  17. 17. sorted() sans Callbacksclass Person(object): >>> people = [Person def __init__(self, f, s): (John, Smith), self.f = f ... Person(Mary, Doe), self.s = s ... Person(Lucy, Pearl),] def __str__(self): >>> for p in sorted(people): return %s %s % (self.f, self. ... print ps) ... def __eq__(self, other): Mary Doe return self.s == other.s Lucy Pearl def __lt__(self, other): John Smith return self.s < other.s >>>
  18. 18. sorted() with Callbacksclass Person(object): >>> for p in sorted(people, def __init__(self, f, s): key=first_name): self.f = f ... print p self.s = s ... def __str__(self): John Smith return %s %s % (self.f, self. Lucy Pearls) Mary Doe >>> for p in sorted(people,first_name = lambda p: p.f key=surname_name):surname = lambda p: p.s ... print p ... Mary Doe Lucy Pearl John Smith >>>
  19. 19. operator module from operator import attrgetter● attrgetter● itemgetter class Person(object):● add def __init__(self, f, s):● mul self.f = f self.s = s● pow def __str__(self): return %s %s % (self.f, self. s) first_name = attrgetter(f) surname = attrgetter(s)
  20. 20. Operations on collections of objects >>> def square(x):● sum ... return x ** 2● filter ...● map >>> l = [1, 2, 3, 4, 5]● reduce >>> 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
  21. 21. itertools module● cycle()● repeat()● chain()● tee()● product()● and many more...
  22. 22. Decoratorsdef cache(fn, c=None): def cache(fn, c=None): if c is None: c = {} if c is None: c = {} def cached(*args): def cached(*args): if args in c: if args in c: return c[args] return c[args] result = fn(*args) result = fn(*args) c[args] = result c[args] = result return result return result return cached return cacheddef adder(x, y): @cache return x + y def adder(x, y): return x + yadder = cache(adder)Do not write code like this, use: functools.lru_cache
  23. 23. 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
  24. 24. RoadmapThesis AntithesisObject Orientation is a proven Functional Programming is away of creating models in long standing approach tosoftware that represent the defining processes in terms ofproblem domain in a useful others at different levels ofmanner. There are many abstraction. Higher orderpatterns that show how to functions make the idiomaticachieve the modularity goal in ways to perform certain tasksdifferent contexts. fall out naturally. 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 donot only exist but they complement each other.
  25. 25. Best of Both Worlds
  26. 26. Unbound methods>>> food = [Spam, ham, ● Functions are descriptorsCheese, eggs] ● Override binding behaviour>>> sorted(food) ● Override differently for A.x[Cheese, Spam, eggs, ham] and a.x>>> sorted(food, key=str.lower) ● Unbound methods know[Cheese, eggs, ham, Spam] their class but not their>>> instance ● Ideal for use in a functional style>>> sorted(food, key=ham.lower)Traceback (most recent call last): File "<stdin>", line 1, in<module>TypeError: lower() takes no
  27. 27. Computed fields (property) class Person(object):class Person(object): def __init__(self, f, s): def __init__(self, f, s): self.f = f self.f = f self._s = s self.s = s @property @property def s(self): def fullname(self): return self._s.upper() return %s %s % (self.f, @s.setter self.s) def s(self, value): self._s = value>>> p = Person(John, Smith)>>> p.fullname >>> p = Person(Jane,John Smith Doe) >>> p.s DOE property([fget[, fset[, fdel[, doc]]]])
  28. 28. property and inheritanceclass Person(object): class Person(object): def __init__(self, t, f, s): def __init__(self, t, f, s): ... ... def full(self): def full(self): return %s %s % (self.f, return %s %s % (self.f, self.s) self.s) fullname = property(full) def _full(self): return self.full()class Customer(Person): fullname = property(_full) def full(self): return %s. %s %s class Customer(Person):% (self.t, self.f, def full(self):self.s) return %s. %s %s % (self.t, self.f, >>> c = Customer(Mr, self.s)John, Smith)>>> c.fullname >>> c.fullname
  29. 29. Dependency Inversionclass Employee(object): def employee_fact(f, s): def __init__(self, f, s): return Employee(f, s) self.f = f self.s = s def register(emps, fact): def register(self): for f, s in emps: pass # Register me emp = fact(f, s) emp.register()def register(emps): for f, s in emps: >>> emps = [(John, emp = Employee(f, s) Smith), (Mary, Doe)] emp.register() >>>register(emps, employee_fact)>>> emps = [(John,Smith), (Mary, Doe)]>>>register(emps)
  30. 30. Python classes are factoriesclass Employee(object): ● Python classes are callables def __init__(self, f, s): ● Indistinguishable from other self.f = f callables to the caller self.s = s ● Allow us to postpone the def register(self): creation of a factory until it pass # Register me actually neededdef register(emps, fact): for f, s in emps: emp = fact(f, s) emp.register()>>> emps = [(John, Smith),(Mary, Doe)]>>>register(emps,Employee)
  31. 31. Many types of callables class Callable(object): ● Functions def __init__(self, m): ● Unbound methods self.message = m def __call__(self): ● Bound methods print self.message ● Classes class NotCallable(object): ● Any object that has a def call(self): __call__ method is a print "You Rang?" callable ● Testable using the >>> c = Callable(You Rang) >>> c() callable built-in function You Rang >>> n = NotCallable()>>> callable(str) >>> n()True Traceback (most recent call last):>>> callable(Spam) File "<stdin>", line 1, in <module>False TypeError: NotCallable object is not>>> callable
  32. 32. RoadmapThesis AntithesisObject Orientation is a proven Functional Programming is away of creating models in long standing approach tosoftware that represent the defining processes in terms ofproblem domain in a useful others at different levels ofmanner. There are many abstraction. Higher orderpatterns that show how to functions make the idiomaticachieve the modularity goal in ways to perform certain tasksdifferent contexts. fall out naturally. 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.
  33. 33. We hire superheroes!● www.demonware.net/jobs/● Development & Operations Positions● Come talk to me any time or meet me at the hiring event

×