Brian Beck showed how to use metaclasses and descriptors to make DSLs with python.
I do this kind of this kind of thing every so often in my code:
def f(x):
class C(object):
y = x
return C
That function takes a parameter and makes and returns a class based on that parameter. Whoop-di-do. I was surprised to learn that you can’t do this:
class C(object):
x = 99
class D(object):
y = x + 1
I gotta explore this some more until it makes sense.
Here’s another neat trick: It isn’t possible to add two classes together:
>>> class C(object):
... pass
...
>>> C + C
------------------------------------------------------------
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for +: 'type' and 'type'
But if you want to support this, the solution would be to define an __add__ method on the metaclass:
>>> type(C)
>>> class MC(type):
... def __add__(self, other):
... print 'Adding!'
... return 99
...
>>> class C(object):
... __metaclass__ = MC
...
>>> C + C
Adding!
99
Wacky, right? More realistically, I could build a new class by taking attributes of both classes together. In other words, if class C has a class attribute x, and class D has a class attribute y, then we can use a metaclass to add C and D together to get a new class E, that has both x and y as class attributes.
In this example, C has a class attribute x and D has a class attribute y. When I add the two classes, I get a new class with both of those class attributes.
>>> C.x, D.y
(99, 98)
>>> E = C + D
>>> E.x, E.y
(99, 98)
Here’s the metaclass that allows this sort of nonsense:
class MC(type):
def __add__(self, other):
class E(self):
pass
for k,v in other.__dict__.items():
if k not in ('__dict__', ):
setattr(E, k, v)
return E