Slide 1

Slide 1 text

Snake Snacks FUNCTION COMPOSITION, THE DUMB WAY

Slide 2

Slide 2 text

WHAT WE WANT def inc(n): return n + 1 def double(n): return n * 2 # in the REPL >>> (inc >> double)(2) 6 >>> (double >> inc)(2) 5

Slide 3

Slide 3 text

HOW ARE WE GONNA GET THERE? The Worst Way Possible™

Slide 4

Slide 4 text

DOUBLE UNDERSCORE METHODS

Slide 5

Slide 5 text

DOUBLE UNDERSCORE METHODS

Slide 6

Slide 6 text

DUNDER METHODS

Slide 7

Slide 7 text

DUNDER MIFFLIN

Slide 8

Slide 8 text

DUNDER METHODS, THE NICE WAY class Boss(object): def __init__(self, name): self.name = name def __str__(self): return self.name def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self) def introduce(self): return "Please meet my boss, %s" % self

Slide 9

Slide 9 text

DUNDER METHODS, THE NICE WAY >>> b = Boss("Michael Scott") >>> b >>> str(b) 'Michael Scott' >>> b.introduce() 'Please meet my boss, Michael Scott'

Slide 10

Slide 10 text

! DECORATORS "

Slide 11

Slide 11 text

DECORATORS, THE NICE WAY def memoize(fn): cache = {} def inner(*args, **kwargs): key = str((args, kwargs)) if key not in cache: cache[key] = fn(*args, **kwargs) return cache[key] return inner

Slide 12

Slide 12 text

DECORATORS, THE NICE WAY @memoize def hype(stuff): return "OH YEAH, IT'S %s" % stuff.upper() # is the same as... hype = memoize(lambda stuff: "OH YEAH, IT'S %s" % stuff.upper())

Slide 13

Slide 13 text

DECORATORS, THE NICE WAY >>> hype("cheese") "OH YEAH, IT'S CHEESE" >>> hype("a moose") "OH YEAH, IT'S A MOOSE"

Slide 14

Slide 14 text

BUT… OBJECTS! class memoize(object): def __init__(self, fn): self.cache = {} self.fn = fn def __call__(self, *args, **kwargs): key = str((args, kwargs)) if key not in self.cache: self.cache[key] = self.fn(*args, **kwargs) return self.cache[key]

Slide 15

Slide 15 text

BUT… OBJECTS! >>> hype("cheese") "OH YEAH, IT'S CHEESE" >>> hype("a moose") "OH YEAH, IT'S A MOOSE" >>> hype.cache {"(('a moose',), {})": "OH YEAH, IT'S A MOOSE", "(('cheese',), {})": "OH YEAH, IT'S CHEESE"}

Slide 16

Slide 16 text

__gt__ class ChessPlayer(object): def __init__(self, name, elo): self.name = name self.elo = elo def __gt__(self, other): return self.elo > other.elo

Slide 17

Slide 17 text

__gt__ >>> carlsen = ChessPlayer("Carlsen, Magnus", 2827) >>> almasi = ChessPlayer("Almasi, Zoltan", 2707) >>> carlsen > almasi True >>> carlsen < almasi False

Slide 18

Slide 18 text

OUR FIRST TRY! class composable(object): def __init__(self, fn): self.fn = fn def __call__(self, *args, **kwargs): return self.fn(*args, **kwargs) def __gt__(self, other): return self.__class__( lambda *args, **kwargs: other(self.fn(*args, **kwargs)) )

Slide 19

Slide 19 text

OUR FIRST TRY! @composable def inc(n): return n + 1 @composable def double(n): return n * 2 @composable def triple(n): return n * 3

Slide 20

Slide 20 text

OUR FIRST TRY! >>> (inc > inc)(0) 2 >>> (inc > inc > inc)(0) 2

Slide 21

Slide 21 text

OUR FIRST TRY! ! 1 > 2 > 3 # is equivalent to 1 > 2 and 2 > 3 # NOT (1 > 2) > 3

Slide 22

Slide 22 text

__rshift__ TO THE RESCUE! class composable(object): def __init__(self, fn): self.fn = fn def __call__(self, *args, **kwargs): return self.fn(*args, **kwargs) def __rshift__(self, other): return self.__class__( lambda *args, **kwargs: other(self.fn(*args, **kwargs)) )

Slide 23

Slide 23 text

__rshift__ TO THE RESCUE! >>> (inc >> inc)(0) 2 >>> (inc >> inc >> inc)(0) 3

Slide 24

Slide 24 text

__rshift__ TO THE RESCUE! >>> (inc >> double)(2) 6 >>> (double >> inc)(2) 5 >>> (inc >> double >> triple)(2) 18

Slide 25

Slide 25 text

THANK YOU I'M SORRY