Die Lösung, die ich zuerst in Python bauen würde, ist diese:
Code: Alles auswählen
class Element:
def __init__(self, name):
self.name = name
def __call__(self, *args):
return "<%s>%s</%s>" % (self.name, "".join(a for a in args), self.name)
class Html:
def __getattr__(self, name):
return Element(name)
h = Html()
print(h.html(h.body(h.h1("Hello"))))
Sie ist objektorientiert und fummelt nicht an den dicts einer Klasse herum, was ich als Monkey-Patching bezeichnen würde und nur im Notfall einsetzen würde. Sie ist aber recht lang.
Mit `partial` geht es in der `setattr`-Variante auch kürzer:
Code: Alles auswählen
def element(name, *args):
return "<%s>%s</%s>" % (name, "".join(a for a in args), name)
class h: pass
for name in "html body h1".split():
setattr(h, name, partial(element, name))
print(h.html(h.body(h.h1("Hello"))))
Ich nutze hier die Klasse als ein Modul für Arme. Ich mache mir nicht die Mühe, ein Exemplar davon zu bilden, sondern rufe statische Funktionen auf. Finde ich aber immer noch besser, als in einem Modul alles globale Funktionen anzulegen.
Doch ich sagte ja, `setattr` fühlt sich nicht gut an. Da baue ich mir die Klasse lieber gleich selbst:
Code: Alles auswählen
h = type("h", (), { n: partial(element, n) for n in "html body h1".split() })
print(h.html(h.body(h.h1("Hello"))))
Das letzte Beispiel erfordert Python 3.1. In Python 2.x ist eine dict-comprehension nur über Umwege möglich. Für solche Experimente ist aber ein aktuelles Python IMHO genau das richtige.
Stefan