Your SlideShare is downloading. ×
Metaprogrammierung, praktisch
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Metaprogrammierung, praktisch

372
views

Published on

Vortrag auf der PyConDE 2012, 30. Oktober 2012

Vortrag auf der PyConDE 2012, 30. Oktober 2012

Published in: Technology

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
372
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 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. 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. Ü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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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