Metaprogrammierung, praktisch                                   Andi Albrecht                                       PyCon ...
Andi Albrecht – @andialbrecht              Erster Python-Kontakt vor etwa 10 Jahren als              Studentische Hilfskra...
Übersicht       Hintergrund       Ein paar Konzepte       Use-Cases       Sinn oder Unsinn?Hintergrund          Ein paar K...
HintergrundWas ist Metaprogrammierung?              "Programmierung der Programmierung"              "Programmcode erzeugt...
HintergrundWas ist Metaprogrammierung?              "Programmierung der Programmierung"              "Programmcode erzeugt...
HintergrundWas ist Metaprogrammierung?              "Programmierung der Programmierung"              "Programmcode erzeugt...
HintergrundMetaklassen in Python              Wohl bekannteste Form der Metaprogrammierung in              Python         ...
HintergrundMetaklassen in Python       Python 1995: C-Extension                 Python 2.2       Python 1.5               ...
KonzepteMetaprogrammierung in Python              Types              Metaklassen              Dekoratoren              Cod...
Konzeptetype()              type(object) → liefert Typ des Objekts              type(name, bases, namespace) → erzeugt ein...
Konzeptetypes-Modul       import types       # Modul erzeugen       my_mod = types.ModuleType(’foo’, ’doc string’)       m...
KonzepteMetaklassen              Metaklassen modifizieren Klassen              Metaklassen können Meta-Funktionen haben   ...
KonzepteMetaklassen, Beispiel       class PluginRegistry(type):              registry = {}              def __new__(mcls, ...
KonzepteKlassendekoratoren, Definition zur Laufzeit, ...              Klassendekoratoren                           Monkey-...
Use-Cases              Enum-Implementierung mit type (Erstellung neuer Typen)              ORM-API mit Metaklassen (Framew...
Use-CasesEnums       def enum(**enums):           return type(’Enum’, (), enums)       > Numbers = enum(ONE=1, TWO=2, THRE...
Use-CasesDjango-Models       from django.db import model       class Book(model.Model):           author = models.CharFiel...
Use-CasesDjango-Models       from django.db import model       class Book(model.Model):           author = models.CharFiel...
Use-CasesTest-Matrix       class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta):           apicalls = (         ...
Use-CasesTest-Matrix       class TestMatrixMeta(type):              def __new__(mcls, name, bases, attrs):                ...
Sinn oder Unsinn?              Für (fast) alles gibt es auch einen andere Lösung              Debugging wird teils schwier...
Danke!              E-Mail albrecht@prounix.de                     albrecht.andi@gmail.com              Twitter @andialbre...
Nächste SlideShare
Wird geladen in …5
×

Metaprogrammierung, praktisch

690 Aufrufe

Veröffentlicht am

Vortrag auf der PyConDE 2012, 30. Oktober 2012

Veröffentlicht in: Technologie
0 Kommentare
1 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
690
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
2
Aktionen
Geteilt
0
Downloads
7
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Metaprogrammierung, praktisch

  1. 1. Metaprogrammierung, praktisch Andi Albrecht PyCon DE 2012 30. Oktober 2012Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  2. 2. Andi Albrecht – @andialbrecht Erster Python-Kontakt vor etwa 10 Jahren als Studentische Hilfskraft bei der DFG Aktuell: Anwendungsentwickler für Webapplikationen bei ProUnix in Bonn Entwicklung und Pflege mittlerer und großer Systeme OpenSource: Rietveld Code Review Tool, python-sqlparse, CrunchyFrog, hgsvn, ...Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  3. 3. Ü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
  4. 4. HintergrundWas ist Metaprogrammierung? "Programmierung der Programmierung" "Programmcode erzeugt|untersucht|… Programmcode" "Programmcode wird zu Objekten von anderem (Meta-)Programmcode"Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  5. 5. 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
  6. 6. 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
  7. 7. HintergrundMetaklassen in Python Wohl bekannteste Form der Metaprogrammierung in Python Möglichkeiten zur Modifikation von Klassen schon in 1995 als C-Extension möglich (Don Beaudry Hook) Ab Python 1.5 auch ohne C-Extension∗ Echter Support für Metaklassen mit New-Style-Classes in Python 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.htmlHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  8. 8. HintergrundMetaklassen in Python Python 1995: C-Extension Python 2.2 Python 1.5 class Foo(object): class Tracing: __metaclass__ = MyMetaclass def __init__(self, name, bases, namespace): def __call__(self): Python 3 class Instance: def __init__(self, klass): def __getattr__(self, name): class Foo(metaclass=MyMetaclass): pass class BoundMethod: def __init__(self, function, instance): def __call__(self, *args): Trace = Tracing(’Trace’, (), ) class MyTracedClass(Trace): def method1(self, a):Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  9. 9. KonzepteMetaprogrammierung in Python Types Metaklassen Dekoratoren Code-Generierung zur Laufzeit (synthetische Funktionen/Klassen) ...Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  10. 10. Konzeptetype() type(object) → liefert Typ des Objekts type(name, bases, namespace) → erzeugt einen neuen Typ > def my_func(self): . return 42 > Question = type(’Question’, (), {’answer’: my_func}) > Question().answer() < 42Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  11. 11. Konzeptetypes-Modul import types # Modul erzeugen my_mod = types.ModuleType(’foo’, ’doc string’) my_mod.foo = my_func sys.modules[’heyho’] = my_mod import heyho heyho.foo() # Methode erzeugen def answer(self): return 42 class Foo(object): pass foo1 = Foo() foo2 = Foo() foo1.answer = types.MethodType(answer, foo1) foo1.answer() # gibt 42 zurück foo2.answer() # wirft einen AttributeErrorHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  12. 12. KonzepteMetaklassen Metaklassen modifizieren Klassen Metaklassen können Meta-Funktionen haben Beispiel für Einsatzzwecke: neue Typen von Klassen neues Verhalten von Klassen Automatisierungen Registrierung von Klassen Frameworks, ORMs Introspektion, QAHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  13. 13. 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) @classmethod def register(mcls, cls): mcls.registry[cls.__name__] = cls @classmethod def get_all(cls): return cls.registry class Foo(metaclass=PluginRegistry): pass class Bar(metaclass=PluginRegistry): pass PluginRegistry.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück Foo.get_all() # –> gibt {’Foo’: <class Foo>, ’Bar’: <class Bar>} zurück Foo().get_all() # –> AttributeErrorHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  14. 14. KonzepteKlassendekoratoren, Definition zur Laufzeit, ... Klassendekoratoren Monkey-Patching import amodule @my_classdecorator class Foo(object): def better_func(): pass print(’This is better!’) return None Code-Generierung zur Laufzeit amodule.func = better_func namespace = {} ... exec(”””def answer(): return 42”””, namespace) namespace[’answer’]() # 42 aber exec lieber vermeiden!Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  15. 15. 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
  16. 16. Use-CasesEnums def enum(**enums): return type(’Enum’, (), enums) > Numbers = enum(ONE=1, TWO=2, THREE=’three’) > Numbers.ONE 1 > Numbers.TWO 2 > 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.RED 0 Siehe http://stackoverflow.com/a/1695250/97167Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  17. 17. 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
  18. 18. 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 Djangos Metaklasse macht (unter anderem): verschiebt "Meta" nach "_meta" und erstellt eigenes Objekt fügt neue DoesNotExist/MultipleObjectsReturned-Attribute hinzu ergänzt einen Record-Manager als "objects"-Attribut wertet die gegebenen Attribute (Namespace) aus und macht sie fit zur Verwendung mit einer DB ...Hintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  19. 19. Use-CasesTest-Matrix class ApiTestCase(unittest.TestCase, metaclass=TestMatrixMeta): apicalls = ( (’/user/1’, ’GET’, {’name’: ’foo’}), (’/user/1/locations’, ’GET’, [’Leipzig’,]), ) python3 testmatrix.py -v test__user_1_json (__main__.test__user_1_locations_xml) ... ok test__user_1_locations_json (__main__.test__user_1_locations_xml) ... ok test__user_1_locations_xml (__main__.test__user_1_locations_xml) ... FAIL test__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_wrapper self.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
  20. 20. 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 @classmethod def 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__ = name return 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
  21. 21. Sinn oder Unsinn? Für (fast) alles gibt es auch einen andere Lösung Debugging wird teils schwieriger, Fehlverhalten nicht immer transparent Verwendung des Codes wird für End-Entwickler eleganter Leichte Erweiterung der Sprache um spezielle Paradigmen, Funktionen, Verhalten, Qualitätsrichtlinien, … → Metaprogrammierung gezielt einsetzen → Einsatz transparent machenHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012
  22. 22. Danke! E-Mail albrecht@prounix.de albrecht.andi@gmail.com Twitter @andialbrecht Homepage http://andialbrecht.de http://www.prounix.de/unternehmen/jobs/python/ prounix.deHintergrund Ein paar Konzepte Use-Cases Sinn oder Unsinn?... ..... ..... Metaprogrammierung, praktisch / Andi Albrecht / PyCon DE 2012

×