View
160
Download
0
Category
Preview:
Citation preview
Abstract Base ClassesA smart use of metaclasses in Python
LEonardo GIordani @LGiordani
http://thedigitalcatonline.com
Abstract Base Classes – LEonardo GIordani - @LGiordani
About Me
Born in 1977 with Star Wars, bash, Apple ][, BSD, finger, Zork, Galaxy Express 999, Little Pollon, Dire Straits, The Police, Rumours, The Silmarillion, Squad Leader.
Interested in operating systems and computer languages, photography, fantasy and science fiction, video- and boardgames, guitar playing, climbing, horseback riding, Aikido, rollerskating,
drawing, painting, bookbinding.
I programmed in Z80 and x86 Assembly, GW-Basic, Logo, Borland Turbo Pascal, Prolog, C, C++, PHP, Lisp, Ada, Objective-C, bash, Python, Erlang, Clojure, Scala, JavaScript.
I love mathematics and cryptography.
tl; dr
me = nerd + coder
Abstract Base Classes – LEonardo GIordani - @LGiordani
Overview
EAFP and complex tests – Polymorphism – Collections
Registering – Abstract Base Classes – Categories
Build your ABCs – MRO with metaclasses – Mixins
Level 1
Level 2
Level 3
Abstract Base Classes – LEonardo GIordani - @LGiordani
Level 1
Abstract Base Classes – LEonardo GIordani - @LGiordani
OOP: behaviour over structure
Abstract Base Classes – LEonardo GIordani - @LGiordani
Python EAFPTest the behaviour, not the structure
try: someobj[1]except TypeError: # object is not subscriptable ...
Abstract Base Classes – LEonardo GIordani - @LGiordani
Some checks are complex.How to check if something behaves like a list?
try: someobj.append someobj.extend someobj.index ...except AttributeError: ...
This is checking the structure: wrong.
Abstract Base Classes – LEonardo GIordani - @LGiordani
Temptation
if isinstance(someobj, list): ...
This is checking the type: wrong.
Abstract Base Classes – LEonardo GIordani - @LGiordani
Python is strongly based on delegation.Change isinstance() and issubclass():
issubclass(myclass, someclass)
someclass.__subclasscheck__(myclass)
becomes
Abstract Base Classes – LEonardo GIordani - @LGiordani
Collectionsclasses that represent interesting behaviours
>>> import collections>>>>>> isinstance(“a string”, collections.Sequence)True>>>>>> isinstance(“a string”, collections.Mapping)False>>>
Abstract Base Classes – LEonardo GIordani - @LGiordani
Level 2
Abstract Base Classes – LEonardo GIordani - @LGiordani
being a subclass in python
Abstract Base Classes – LEonardo GIordani - @LGiordani
Either a class is a REAL subclass
class ChildClass(ParentClass): pass
Abstract Base Classes – LEonardo GIordani - @LGiordani
Or a VIRTUAL subclass
ParentClass.register(ChildClass)
Abstract Base Classes – LEonardo GIordani - @LGiordani
Classes that can register() other classes are calledAbstract Base Classes or ABCs.
...Sequence.register(tuple)Sequence.register(str)Sequence.register(range)...MutableSequence.register(list)...
from python3.4/_collections_abc.py
Abstract Base Classes – LEonardo GIordani - @LGiordani
registering is a promise: no check!
Abstract Base Classes – LEonardo GIordani - @LGiordani
Example
>>> import collections>>> class MyClass:... pass... >>>
Abstract Base Classes – LEonardo GIordani - @LGiordani
Example
>>> import collections>>> class MyClass:... pass... >>> issubclass(MyClass, collections.Sequence)False>>>
Abstract Base Classes – LEonardo GIordani - @LGiordani
Example
>>> import collections>>> class MyClass:... pass... >>> issubclass(MyClass, collections.Sequence)False>>> collections.Sequence.register(MyClass)<class '__main__.MyClass'>>>> issubclass(MyClass, collections.Sequence)True>>>
Abstract Base Classes – LEonardo GIordani - @LGiordani
Abstract base classes are categories
Abstract Base Classes – LEonardo GIordani - @LGiordani
Level 3
Abstract Base Classes – LEonardo GIordani - @LGiordani
HOW TO DEFINE YOUR ABC
Abstract Base Classes – LEonardo GIordani - @LGiordani
Build your own Abstract Base Class(stright from the docs)
from abc import ABCMeta
class MyABC(metaclass=ABCMeta): pass
MyABC.register(tuple)
assert issubclass(tuple, MyABC)assert isinstance((), MyABC)
Abstract Base Classes – LEonardo GIordani - @LGiordani
WHY METACLASSES?
Abstract Base Classes – LEonardo GIordani - @LGiordani
DON'T PANIC(The Hitchhiker's Guide to the Galaxy)
Abstract Base Classes – LEonardo GIordani - @LGiordani
When you build an instance you use a class.The class can put things into the instance.
# Class definitionclass Child():
def __init__(self):self.answer = 42
# Link instance and classc = Child()
# Use the instanceassert c.answer == 42
Abstract Base Classes – LEonardo GIordani - @LGiordani
When you build a class you use a metaclass.The metaclass can put things into the class.
# Metaclass definitionclass NewType(type):
def __init__(self, name, bases, namespace):self.answer = 42
# Link class and metaclassclass Child(metaclass=NewType): pass
# Use the classassert Child.answer == 42
Abstract Base Classes – LEonardo GIordani - @LGiordani
it. is. simple.
Abstract Base Classes – LEonardo GIordani - @LGiordani
What happens to the MRO?
class Parent: @classmethod def whoami(cls): return "Parent"
class NewType(type): def whoami(self): return "NewType"
class Child(Parent, metaclass=NewType): pass
assert Child.whoami() == “Parent”
Abstract Base Classes – LEonardo GIordani - @LGiordani
METACLASSES ARE MIXINS FOR CLASSES
Abstract Base Classes – LEonardo GIordani - @LGiordani
Check the documentation for @abstractmethod and @abstractproperty
class Hashable(metaclass=ABCMeta):
[...]
@abstractmethod def __hash__(self): return 0
[...]
Abstract Base Classes – LEonardo GIordani - @LGiordani
Questions & ANSWERS
Abstract Base Classes – LEonardo GIordani - @LGiordani
Interested in AMQP, C, Clojure, concurrent programming, C++, decorators, Django, Erlang, functional programming, generators, Git, metaclasses, metaprogramming, Notebook, OOP, operating systems,
Python, Qt, RabbitMQ, Scala, TDD, versioning?
http://thedigitalcatonline.com@thedigicat
Abstract Base Classes – LEonardo GIordani - @LGiordani
THANKS
Recommended