act i: exposition where we meet our characters and the world they live in

56
Composability through Multiple Inheritance A drama in Three Acts by Łukasz Langa

Upload: zachary-wallace

Post on 26-Mar-2015

214 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Act I: Exposition where we meet our characters and the world they live in

Composabilitythrough Multiple Inheritance

A drama in Three Actsby Łukasz Langa

Page 2: Act I: Exposition where we meet our characters and the world they live in

Act I: Expositionwhere we meet our characters and the world they

live in

Page 3: Act I: Exposition where we meet our characters and the world they live in
Page 4: Act I: Exposition where we meet our characters and the world they live in

Composability

Page 5: Act I: Exposition where we meet our characters and the world they live in

Compositionality

Page 6: Act I: Exposition where we meet our characters and the world they live in

Unix pipes

$ ps aux | grep celery | grep -v grep |awk '{print $2}' | xargs kill -9

Page 7: Act I: Exposition where we meet our characters and the world they live in

Unix pipes

$ ps aux | grep celery | grep -v grep |awk '{print $2}' | xargs kill -9

Page 8: Act I: Exposition where we meet our characters and the world they live in

Unix pipes

$ command1 | command2 | command3 | ...

Page 9: Act I: Exposition where we meet our characters and the world they live in

Godtfred Kirk Christiansen

Page 10: Act I: Exposition where we meet our characters and the world they live in
Page 11: Act I: Exposition where we meet our characters and the world they live in

Joe Armstrong

Page 12: Act I: Exposition where we meet our characters and the world they live in

Joe Armstrong

grep REGEX <file >matches

Page 13: Act I: Exposition where we meet our characters and the world they live in

Quality

Page 14: Act I: Exposition where we meet our characters and the world they live in
Page 15: Act I: Exposition where we meet our characters and the world they live in

Robert M. Pirsig

Page 16: Act I: Exposition where we meet our characters and the world they live in

Jamie Zawinski

Page 17: Act I: Exposition where we meet our characters and the world they live in

Quality

ComposabilityCompositiona

lity

Page 18: Act I: Exposition where we meet our characters and the world they live in

Act II: Rising Actionwhere we learn how inheritance in Python works

Page 19: Act I: Exposition where we meet our characters and the world they live in

If you use old-style classes

You’re gonna have a bad time

Page 20: Act I: Exposition where we meet our characters and the world they live in

Method Resolution Order

>>> class A(object):... pass... ... >>> A.mro()[<class '__main__.A'>, <type 'object'>]

Page 21: Act I: Exposition where we meet our characters and the world they live in

Method Resolution Order

object

A

Page 22: Act I: Exposition where we meet our characters and the world they live in

Method Resolution Order

>>> class A(object): pass... >>> class B(object): pass... >>> class AB(A, B): pass...

Page 23: Act I: Exposition where we meet our characters and the world they live in

The Diamond Problem

object

A B

AB

Page 24: Act I: Exposition where we meet our characters and the world they live in

The Diamond ”Problem”

object

A B

AB

Page 25: Act I: Exposition where we meet our characters and the world they live in

The Diamond ”Problem”

>>> class A(object): pass... >>> class B(object): pass... >>> class AB(A, B): pass... >>> AB.mro()[<class '__main__.AB'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]

Page 26: Act I: Exposition where we meet our characters and the world they live in

Method Resolution Order

>>> class A(object):... def say(self, what):... return what + 'a’ ... >>> class B(object):... def say(self, what):... return what + 'b’... >>> class AB(A, B): pass... >>> class BA(B, A): pass... >>> AB().say('hello:')'hello:a'>>> BA().say('hey:')'hey:b'

Page 27: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class A(object): def __init__(self, arg_a): self.arg_a = arg_a

class B(object): def __init__(self, arg_b): self.arg_b = arg_b

class AB(A, B): def __init__(self, arg_a, arg_b): # ???

Page 28: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class A(object): def __init__(self, arg_a): self.arg_a = arg_a

class B(object): def __init__(self, arg_b): self.arg_b = arg_b

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

Page 29: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

>>> ab = AB('a', 'b')>>> ab.arg_a'a'>>> ab.arg_b'b'

Page 30: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

class C(D, AB): def __init__(self, arg_c): D.__init__(self) AB.__init__(self, *arg_c.split('.', 1))

>>> c=C('1.0')>>> c.arg_a'1'>>> c.arg_b'0’

Page 31: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

class C(D, AB): def __init__(self, arg_c): D.__init__(self) AB.__init__(self, *arg_c.split('.', 1))

>>> C.mro()[<class '__main__.C'>, <class '__main__.D'>, <class '__main__.AB'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]

Page 32: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

class D(A): def __init__(self): A.__init__(self, 'd')

class C(D, AB): def __init__(self, arg_c): D.__init__(self) AB.__init__(self, *arg_c.split('.', 1))

Page 33: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): A.__init__(self, arg_a) B.__init__(self, arg_b)

class C(D, AB): def __init__(self, arg_c): D.__init__(self) AB.__init__(self, *arg_c.split('.', 1))

>>> C.mro()[<class '__main__.C'>, <class '__main__.D'>, <class '__main__.AB'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]

A.__init__(self, arg_a)

super(AB, self).__init__(arg_a)

Page 34: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class AB(A, B): def __init__(self, arg_a, arg_b): super(AB, self).__init__(arg_a=arg_a, arg_b=arg_b)

class D(A): def __init__(self): super(D, self).__init__(arg_a='d')

class C(D, AB): def __init__(self, arg_c): super(C, self).__init__( *arg_c.split('.', 1))

Page 35: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class D(A): def __init__(self): super(D, self).__init__(arg_a='d')

class C(D, AB): def __init__(self, arg_c): super(C, self).__init__( *arg_c.split('.', 1))

>>> C('1.0')Traceback (most recent call last): File "<input>", line 1, in <module> File "mrosuper.py", line 27, in __init__ super(C, self).__init__(*arg_c.split('.', 1))TypeError: __init__() takes exactly 1 argument (3 given)

Page 36: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

class D(A): def __init__(self): super(D, self).__init__(arg_a='d')

class C(D, AB): def __init__(self, arg_c): super(C, self).__init__( *arg_c.split('.', 1))

>>> C('1.0')Traceback (most recent call last): File "<input>", line 1, in <module> File "mrosuper.py", line 27, in __init__ super(C, self).__init__(*arg_c.split('.', 1))TypeError: __init__() takes exactly 1 argument (3 given)

Page 37: Act I: Exposition where we meet our characters and the world they live in

class A(object): def __init__(self, arg_a, **kwargs): self.arg_a = arg_a super(A, self).__init__(**kwargs)

class B(object): def __init__(self, arg_b, **kwargs): self.arg_b = arg_b super(B, self).__init__(**kwargs)

class AB(A, B): def __init__(self, arg_a, arg_b, **kwargs): super(AB, self).__init__(arg_a=arg_a, arg_b=arg_b, **kwargs)

class D(A): def __init__(self, **kwargs): super(D, self).__init__(arg_a='d', **kwargs)

class C(D, AB): def __init__(self, arg_c, **kwargs): super(C, self).__init__(*arg_c.split('.', 1), **kwargs)

Page 38: Act I: Exposition where we meet our characters and the world they live in

class A(object): def __init__(self, arg_a, **kwargs): self.arg_a = arg_a super(A, self).__init__(**kwargs)

class B(object): def __init__(self, arg_b, **kwargs): self.arg_b = arg_b super(B, self).__init__(**kwargs)

class AB(A, B): def __init__(self, arg_a, arg_b, **kwargs): super(AB, self).__init__(arg_a=arg_a, arg_b=arg_b, **kwargs)

class D(A): def __init__(self, **kwargs): super(D, self).__init__(arg_a='d', **kwargs)

class C(D, AB): def __init__(self, arg_c, **kwargs): super(C, self).__init__(*arg_c.split('.', 1), **kwargs)

Page 39: Act I: Exposition where we meet our characters and the world they live in

class A(object): def __init__(self, arg_a, **kwargs): self.arg_a = arg_a super(A, self).__init__(**kwargs)

class B(object): def __init__(self, arg_b, **kwargs): self.arg_b = arg_b super(B, self).__init__(**kwargs)

class AB(A, B): def __init__(self, arg_a, arg_b, **kwargs): super(AB, self).__init__(arg_a=arg_a, arg_b=arg_b, **kwargs)

class D(A): def __init__(self, **kwargs): super(D, self).__init__(arg_a='d', **kwargs)

class C(D, AB): def __init__(self, arg_c, **kwargs): super(C, self).__init__(*arg_c.split('.', 1), **kwargs)

Page 40: Act I: Exposition where we meet our characters and the world they live in

THIS SHIT IS HARD

Page 41: Act I: Exposition where we meet our characters and the world they live in

class A(object): def __init__(self, arg_a, **kwargs): self.arg_a = arg_a super(A, self).__init__(**kwargs)class B(object): def __init__(self, arg_b, **kwargs): self.arg_b = arg_b super(B, self).__init__(**kwargs)class AB(A, B): def __init__(self, arg_a, arg_b, **kwargs): kwargs['arg_a'], kwargs['arg_b'] = arg_a, arg_b super(AB, self).__init__(**kwargs)class D(A): def __init__(self, **kwargs): kwargs['arg_a'] = 'd' super(D, self).__init__(**kwargs)class C(D, AB): def __init__(self, arg_c, **kwargs): kwargs['arg_a'], kwargs['arg_b'] = arg_c.split('.', 1) super(C, self).__init__(**kwargs)

Page 42: Act I: Exposition where we meet our characters and the world they live in

It’s still different!

>>> c=C('1.0')>>> c.arg_au'd'>>> c.arg_bu'0'

Page 43: Act I: Exposition where we meet our characters and the world they live in

Cooperative Inheritance

Don’t omit super(C, self).__init__() even if your base class is object

Don’t assume you know what arguments you’re going to get

Don’t assume you know what arguments you should pass to super always pass all arguments you received

on to super if classes can take differing arguments,

always accept **kwargs

Page 44: Act I: Exposition where we meet our characters and the world they live in

If you mix Class.__init__ and super()

You’re gonna have a bad time

Page 45: Act I: Exposition where we meet our characters and the world they live in

Mixins

Not meant for instantiation on their own

Enhance classes with independent functionality

Not a form of specialisation but collection of functionality

Like interfaces with built-in implementation

Very reusable if orthogonal to the main type

Page 46: Act I: Exposition where we meet our characters and the world they live in

InterludeDjango ORM inheritance model

sucks

Page 47: Act I: Exposition where we meet our characters and the world they live in

The Diamond Problem

M1

M2 M3

M4

Page 48: Act I: Exposition where we meet our characters and the world they live in

Polymorphism

M1

M2

M3 M

4

Page 49: Act I: Exposition where we meet our characters and the world they live in

Liskov substitution principle

M1

M2

M3 M

4

Page 50: Act I: Exposition where we meet our characters and the world they live in

Act III: The Climax

Page 51: Act I: Exposition where we meet our characters and the world they live in

Yep,here comes the demo.

Page 52: Act I: Exposition where we meet our characters and the world they live in

And by the way

Just so you know.

Page 53: Act I: Exposition where we meet our characters and the world they live in
Page 54: Act I: Exposition where we meet our characters and the world they live in
Page 55: Act I: Exposition where we meet our characters and the world they live in

Jamie Zawinski

Page 56: Act I: Exposition where we meet our characters and the world they live in

Questions?

ambvat #python-dev IRC

@llangaon Twitter

[email protected] a last resort