Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.

Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.

Like this presentation? Why not share!

873 views

Published on

Published in:
Technology

No Downloads

Total views

873

On SlideShare

0

From Embeds

0

Number of Embeds

2

Shares

0

Downloads

22

Comments

0

Likes

3

No embeds

No notes for slide

- 1. Object Orientation vs. Functional Programming Writing Modular Python Programs Twitter: @insmallportions www.insmallportions.com
- 2. About Me
- 3. Modularity
- 4. Roadmap <ul><li>Thesis </li></ul><ul><li>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. </li></ul><ul><li>Antithesis </li></ul><ul><li>Functional 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. </li></ul>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.
- 5. Object Orientation <ul><ul><li>Class Oriented </li></ul></ul><ul><li> </li></ul><ul><ul><li>The Three Pillars of OO are: </li></ul></ul><ul><ul><li>Delegation </li></ul></ul><ul><ul><li>Polymorphism </li></ul></ul><ul><ul><li>Instantiation </li></ul></ul>
- 6. 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
- 7. 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__
- 8. 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()
- 9. 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
- 10. Wrapping/Composition <ul><ul><li>Prefer Composition over Inheritance </li></ul></ul><ul><ul><li>Use a class's functionality but not its API </li></ul></ul><ul><ul><li>Expose only limited part of an object </li></ul></ul><ul><li> </li></ul><ul><ul><li>Typical uses: </li></ul></ul><ul><ul><ul><li>Adapt </li></ul></ul></ul><ul><ul><ul><li>Proxy </li></ul></ul></ul><ul><ul><ul><li>Decorate </li></ul></ul></ul>
- 11. 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 data.safe(): self._eprom.write(data) def close(self): self._eprom.complete()
- 12. 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() <ul><ul><li>Don't Repeat Yourself </li></ul></ul><ul><ul><li>Avoid boilerplate </li></ul></ul><ul><ul><li>Use __getattr__ to return computed attributes </li></ul></ul>
- 13. Mixins Again class SafeAndFileLike(FileLikeEprom, SafeEprom): def __init__(self, *args, **kwargs): return super(SafeAndFileLike, self).__init__(*args, **kwargs)
- 14. Roadmap <ul><li>Thesis </li></ul><ul><li>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. </li></ul><ul><li>Antithesis </li></ul><ul><li>Functional 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. </li></ul>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.
- 15. Functional Programming <ul><ul><li>Functions take input and produce output, without any side effects. </li></ul></ul><ul><ul><li>Pure functional languages are strict about side effect freeness. </li></ul></ul><ul><ul><li>Python is not a pure functional language. </li></ul></ul><ul><ul><li>Functions may be internally imperative, but appear purely functional in their behaviour. </li></ul></ul>
- 16. Callbacks <ul><ul><li>The Hollywood principle </li></ul></ul><ul><ul><li>Role reversal, library code calls your code </li></ul></ul><ul><ul><li>Library code accepts a callable and invokes it when appropriate </li></ul></ul><ul><li> </li></ul><ul><ul><li>The main uses: </li></ul></ul><ul><ul><ul><li>Customisation </li></ul></ul></ul><ul><ul><ul><li>Event Handling </li></ul></ul></ul>
- 17. sorted() sans Callbacks <ul><li>>>> people = [Person('John', 'Smith'), ... Person('Mary', 'Doe'), ... Person('Lucy', 'Pearl'),] >>> for p in sorted(people): ... print p ... Mary Doe Lucy Pearl John Smith >>> </li></ul>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
- 18. sorted() with Callbacks <ul><li>>>> for p in sorted(people, key=first_name): ... print p ... John Smith Lucy Pearl Mary Doe >>> for p in sorted(people, key=surname_name): ... print p ... Mary Doe Lucy Pearl John Smith >>> </li></ul>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.f surname = lambda p: p.s
- 19. 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') <ul><ul><li>attrgetter </li></ul></ul><ul><ul><li>itemgetter </li></ul></ul><ul><ul><li>add </li></ul></ul><ul><ul><li>mul </li></ul></ul><ul><ul><li>pow </li></ul></ul><ul><ul><li>... </li></ul></ul>
- 20. Operations on aggregates <ul><ul><li>sum </li></ul></ul><ul><ul><li>filter </li></ul></ul><ul><ul><li>map </li></ul></ul><ul><ul><li>reduce </li></ul></ul>>>> 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
- 21. itertools module <ul><ul><li>cycle() </li></ul></ul><ul><ul><li>repeat() </li></ul></ul><ul><ul><li>chain() </li></ul></ul><ul><ul><li>tee() </li></ul></ul><ul><ul><li>product() </li></ul></ul><ul><ul><li>... </li></ul></ul>
- 22. Decorators <ul><li>def cache(fn, c=None): </li></ul><ul><li> 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 </li></ul><ul><li> </li></ul><ul><li>adder = cache(adder) </li></ul>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 Do not write code like this, use: functools.lru_cache
- 23. Partial function evaluation <ul><li>>>> 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 </li></ul>
- 24. Roadmap <ul><li>Thesis </li></ul><ul><li>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. </li></ul><ul><li>Antithesis </li></ul><ul><li>Functional 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. </li></ul>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.
- 25. Best of Both Worlds
- 26. Unbound methods <ul><ul><li>Functions are descriptors </li></ul></ul><ul><ul><li>Override binding behaviour </li></ul></ul><ul><ul><li>Override differently for A.x and a.x </li></ul></ul><ul><ul><li>Unbound methods know their class but not their instance </li></ul></ul><ul><ul><li>Ideal for use in a functional style </li></ul></ul>>>> 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)
- 27. 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 ]]]])
- 28. property and inheritance class 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'
- 29. 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)
- 30. 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) <ul><ul><li>Python classes are callables </li></ul></ul><ul><ul><li>Indistinguishable from other callables to the caller </li></ul></ul><ul><ul><li>Allow us to postpone the creation of a factory until it actually needed </li></ul></ul>
- 31. Many types of callables <ul><ul><li>Functions </li></ul></ul><ul><ul><li>Unbound methods </li></ul></ul><ul><ul><li>Bound methods </li></ul></ul><ul><ul><li>Classes </li></ul></ul><ul><ul><li>Any object that has a __call__ method is a callable </li></ul></ul><ul><ul><li>Testable using the callable built-in function </li></ul></ul><ul><li> </li></ul><ul><li>>>> callable(str) True >>> callable('Spam') False >>> </li></ul>class Callable(object): def __init__(self, m): self.message = m def __call__(self): print self.message class 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
- 32. Roadmap <ul><li>Thesis </li></ul><ul><li>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. </li></ul><ul><li>Antithesis </li></ul><ul><li>Functional 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. </li></ul>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.
- 33. We hire superheroes! <ul><ul><li>www.demonware.net/jobs/ </li></ul></ul><ul><li> </li></ul><ul><ul><li>Development & Operations Positions </li></ul></ul><ul><li> </li></ul><ul><ul><li>Come talk to us </li></ul></ul>

No public clipboards found for this slide

×
### Save the most important slides with Clipping

Clipping is a handy way to collect and organize the most important slides from a presentation. You can keep your great finds in clipboards organized around topics.

Be the first to comment