Act I: Exposition where we meet our characters and the world they live in.
-
Upload
zachary-wallace -
Category
Documents
-
view
215 -
download
1
Transcript of Act I: Exposition where we meet our characters and the world they live in.
Composabilitythrough Multiple Inheritance
A drama in Three Actsby Łukasz Langa
Act I: Expositionwhere we meet our characters and the world they
live in
Composability
Compositionality
Unix pipes
$ ps aux | grep celery | grep -v grep |awk '{print $2}' | xargs kill -9
Unix pipes
$ ps aux | grep celery | grep -v grep |awk '{print $2}' | xargs kill -9
Unix pipes
$ command1 | command2 | command3 | ...
Godtfred Kirk Christiansen
Joe Armstrong
Joe Armstrong
grep REGEX <file >matches
Quality
Robert M. Pirsig
Jamie Zawinski
Quality
ComposabilityCompositiona
lity
Act II: Rising Actionwhere we learn how inheritance in Python works
If you use old-style classes
You’re gonna have a bad time
Method Resolution Order
>>> class A(object):... pass... ... >>> A.mro()[<class '__main__.A'>, <type 'object'>]
Method Resolution Order
object
A
Method Resolution Order
>>> class A(object): pass... >>> class B(object): pass... >>> class AB(A, B): pass...
The Diamond Problem
object
A B
AB
The Diamond ”Problem”
object
A B
AB
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'>]
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'
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): # ???
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)
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'
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’
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'>]
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))
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)
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))
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)
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)
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)
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)
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)
THIS SHIT IS HARD
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)
It’s still different!
>>> c=C('1.0')>>> c.arg_au'd'>>> c.arg_bu'0'
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
If you mix Class.__init__ and super()
You’re gonna have a bad time
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
InterludeDjango ORM inheritance model
sucks
The Diamond Problem
M1
M2 M3
M4
Polymorphism
M1
M2
M3 M
4
Liskov substitution principle
M1
M2
M3 M
4
Act III: The Climax
Yep,here comes the demo.
And by the way
Just so you know.
Jamie Zawinski