Metaprogrammierung, praktisch
-
Upload
andi-albrecht -
Category
Technology
-
view
411 -
download
0
description
Transcript of Metaprogrammierung, praktisch
Metaprogrammierung, praktisch
Andi Albrecht
PyCon DE 2012
30. Oktober 2012
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Andi Albrecht – @andialbrecht
Erster Python-Kontakt vor etwa 10 Jahren alsStudentische Hilfskraft bei der DFGAktuell: Anwendungsentwickler für Webapplikationen beiProUnix in BonnEntwicklung und Pflege mittlerer und großer SystemeOpenSource: Rietveld Code Review Tool,python-sqlparse, CrunchyFrog, hgsvn, ...
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Übersicht
Hintergrund
Ein paar Konzepte
Use-Cases
Sinn oder Unsinn?
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
HintergrundWas ist Metaprogrammierung?
"Programmierung der Programmierung""Programmcode erzeugt|untersucht|… Programmcode""Programmcode wird zu Objekten von anderem(Meta-)Programmcode"
mysterious, strange, weird, mind-blowing, …
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
HintergrundWas ist Metaprogrammierung?
"Programmierung der Programmierung""Programmcode erzeugt|untersucht|… Programmcode""Programmcode wird zu Objekten von anderem(Meta-)Programmcode"mysterious, strange, weird, mind-blowing, …
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
HintergrundWas ist Metaprogrammierung?
"Programmierung der Programmierung""Programmcode erzeugt|untersucht|… Programmcode""Programmcode wird zu Objekten von anderem(Meta-)Programmcode"mysterious, strange, weird, mind-blowing, …
Meta-: jenseits, dahinter liegend, …
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
HintergrundMetaklassen in Python
Wohl bekannteste Form der Metaprogrammierung inPythonMöglichkeiten zur Modifikation von Klassen schon in 1995als C-Extension möglich (Don Beaudry Hook)Ab Python 1.5 auch ohne C-Extension∗
Echter Support für Metaklassen mit New-Style-Classes inPython 2.2
* dazu: Essay von GvR "Metaclasses in Python 1.5 (a.k.a. The Killer Joke)"http://www.python.org/doc/essays/metaclasses/
http://python-history.blogspot.de/2009/04/metaclasses-and-extension-classes-aka.html
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
HintergrundMetaklassen in Python
Python 1995: C-Extension
Python 1.5
class Tracing:def __init__(self,name, bases, namespace):
def __call__(self):
class Instance:def __init__(self, klass):def __getattr__(self, name):
class BoundMethod:def __init__(self,function, instance):
def __call__(self, *args):
Trace = Tracing(’Trace’, (), )
class MyTracedClass(Trace):def method1(self, a):
Python 2.2
class Foo(object):__metaclass__ = MyMetaclass
Python 3
class Foo(metaclass=MyMetaclass):pass
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
KonzepteMetaprogrammierung in Python
TypesMetaklassenDekoratorenCode-Generierung zur Laufzeit (synthetischeFunktionen/Klassen)...
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzeptetype()
type(object) → liefert Typ des Objektstype(name, bases, namespace) → erzeugt einenneuen Typ
> def my_func(self):. return 42
> Question = type(’Question’, (), {’answer’: my_func})> Question().answer()< 42
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Konzeptetypes-Modul
import types
# Modul erzeugenmy_mod = types.ModuleType(’foo’, ’doc string’)my_mod.foo = my_funcsys.modules[’heyho’] = my_modimport heyhoheyho.foo()
# Methode erzeugendef answer(self):
return 42class Foo(object):
passfoo1 = Foo()foo2 = Foo()foo1.answer = types.MethodType(answer, foo1)foo1.answer() # gibt 42 zurückfoo2.answer() # wirft einen AttributeError
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
KonzepteMetaklassen
Metaklassen modifizieren KlassenMetaklassen können Meta-Funktionen habenBeispiel für Einsatzzwecke:
neue Typen von Klassenneues Verhalten von KlassenAutomatisierungenRegistrierung von KlassenFrameworks, ORMsIntrospektion, QA
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
KonzepteMetaklassen, Beispiel
class PluginRegistry(type):
registry = {}
def __new__(mcls, name, bases, classdict):return type.__new__(mcls, name, bases, classdict)
def __init__(cls, name, bases, namespace):PluginRegistry.register(cls)return super(PluginRegistery, cls).__init__(name, bases, namespace)
@classmethoddef register(mcls, cls):
mcls.registry[cls.__name__] = cls
@classmethoddef get_all(cls):
return cls.registry
class Foo(metaclass=PluginRegistry): passclass Bar(metaclass=PluginRegistry): pass
PluginRegistry.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurückFoo.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurückFoo().get_all() # –> AttributeError
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
KonzepteKlassendekoratoren, Definition zur Laufzeit, ...
Klassendekoratoren
@my_classdecoratorclass Foo(object):pass
Code-Generierung zurLaufzeit
namespace = {}exec(”””def answer():return 42”””, namespace)
namespace[’answer’]() # 42
aber exec lieber vermeiden!
Monkey-Patching
import amodule
def better_func():print(’This is better!’)return None
amodule.func = better_func
...
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-Cases
Enum-Implementierung mit type (Erstellung neuer Typen)ORM-API mit Metaklassen (Framework / ORM)Aufbau einer Testmatrix (Automatisierung)
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-CasesEnums
def enum(**enums):return type(’Enum’, (), enums)
> Numbers = enum(ONE=1, TWO=2, THREE=’three’)> Numbers.ONE1> Numbers.TWO2> Numbers.THREE’three’
def enum(name, *sequential):enums = dict(x[::-1] for x in enumerate(sequential))return type(name, (), enums)
> Colors = enum(’Colors’, ’RED’, ’GREEN’, ’BLUE’)> Colors.RED0
Siehe http://stackoverflow.com/a/1695250/97167
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-CasesDjango-Models
from django.db import model
class Book(model.Model):author = models.CharField(max_length=200)title = models.CharField(max_length=200)year = models.IntegerField()
class Meta:verbose_name_plural = u’Books’
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-CasesDjango-Models
from django.db import model
class Book(model.Model):author = models.CharField(max_length=200)title = models.CharField(max_length=200)year = models.IntegerField()
class Meta:verbose_name_plural = u’Books’
...und was Django's Metaklasse macht (unter anderem):verschiebt "Meta" nach "_meta" und erstellt eigenes Objektfügt neue DoesNotExist/MultipleObjectsReturned-Attribute hinzuergänzt einen Record-Manager als "objects"-Attributwertet die gegebenen Attribute (Namespace) aus und macht sie fit zurVerwendung mit einer DB...
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-CasesTest-Matrix
class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta):apicalls = (
(’/user/1’, ’GET’, {’name’: ’foo’}),(’/user/1/locations’, ’GET’, [’Leipzig’,]),
)
python3 testmatrix.py -vtest__user_1_json (__main__.test__user_1_locations_xml) ... oktest__user_1_locations_json (__main__.test__user_1_locations_xml) ... oktest__user_1_locations_xml (__main__.test__user_1_locations_xml) ... FAILtest__user_1_xml (__main__.test__user_1_locations_xml) ... ok
======================================================================FAIL: test__user_1_locations_xml (__main__.test__user_1_locations_xml)———————————————————————-Traceback (most recent call last):File ”testmatrix.py”, line 17, in test_wrapperself.assertFalse(u==’/user/1/locations’ and c == ’xml’)
AssertionError: True is not false
———————————————————————-Ran 4 tests in 0.001s
FAILED (failures=1)
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Use-CasesTest-Matrix
class TestMatrixMeta(type):
def __new__(mcls, name, bases, attrs):apicalls = attrs.pop(’apicalls’, [])for url, method, expected in apicalls:
for ctype in (’json’, ’xml’):name = ’test_%s_%s’ % (url.replace(’/’, ’_’), ctype)attrs[name] = mcls.build_test(name, url, method, expected, ctype)
new_cls = type.__new__(mcls, name, bases, attrs)return new_cls
@classmethoddef build_test(cls, name, url, method, expected, ctype):
def test_wrapper(self, u=url, m=method, e=expected, c=ctype):self.assertFalse(u==’/user/1/locations’ and c == ’xml’)
test_wrapper.__name__ = namereturn test_wrapper
class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta):apicalls = (
(’/user/1’, ’GET’, {’name’: ’foo’}),(’/user/1/locations’, ’GET’, [’Leipzig’,]),
)
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Sinn oder Unsinn?
Für (fast) alles gibt es auch einen andere LösungDebugging wird teils schwieriger, Fehlverhalten nichtimmer transparent
Verwendung des Codes wird für End-Entwickler eleganterLeichte Erweiterung der Sprache um spezielleParadigmen, Funktionen, Verhalten, Qualitätsrichtlinien, …
→ Metaprogrammierung gezielt einsetzen→ Einsatz transparent machen
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
Danke!
E-Mail [email protected]@gmail.com
Twitter @andialbrecht
Homepage http://andialbrecht.de
http://www.prounix.de/unternehmen/jobs/python/
prounix.de
. . .Hintergrund
. . . . .Ein paar Konzepte
. . . . .Use-Cases Sinn oder Unsinn?
Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012