Top Banner
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
22

Metaprogrammierung, praktisch

May 28, 2015

Download

Technology

Andi Albrecht

Vortrag auf der PyConDE 2012, 30. Oktober 2012
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 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

Page 2: Metaprogrammierung, praktisch

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

Page 3: Metaprogrammierung, praktisch

Ü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

Page 4: Metaprogrammierung, praktisch

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

Page 5: Metaprogrammierung, praktisch

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

Page 6: Metaprogrammierung, praktisch

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

Page 7: Metaprogrammierung, praktisch

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

Page 8: Metaprogrammierung, praktisch

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

Page 9: Metaprogrammierung, praktisch

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

Page 10: Metaprogrammierung, praktisch

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

Page 11: Metaprogrammierung, praktisch

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

Page 12: Metaprogrammierung, praktisch

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

Page 13: Metaprogrammierung, praktisch

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

Page 14: Metaprogrammierung, praktisch

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

Page 15: Metaprogrammierung, praktisch

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

Page 16: Metaprogrammierung, praktisch

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

Page 17: Metaprogrammierung, praktisch

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

Page 18: Metaprogrammierung, praktisch

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

Page 19: Metaprogrammierung, praktisch

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

Page 20: Metaprogrammierung, praktisch

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

Page 21: Metaprogrammierung, praktisch

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

Page 22: Metaprogrammierung, praktisch

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