![]() |
Metaprogramming
Can someone please explain metaclasses & metaprogramming? I read a few definitions but I dont understand why they are necessary.... thanks
|
Metaprogramming is the writing of programs that are designed to write/rewrite other programs (or often themselves). Python is relatively well equipped in this regard.
Metaclasses are to classes what classes are to objects. Or, to put it another way, if you instantiate a class, you get an object, whilst if you instantiate a metaclass, you get a class. For instance, a string in Python is instantiated from the str object. The class of a string is str: :
>>> print "Some string".__class__:
>>> "Some string".__class__.__class__Confusingly, type has two functions in Python. If type is called with one argument, it merely returns the type of an object. But if type is called with three arguments, it constructs a new class: :
BlankClass = type("BlankClass", (), {})As well as using the generic type metaclass to construct a new class on the fly, one can dynamically alter existing classes by specifying a metaclass with the __metaclass__ attribute. Before I touch on that, however, I'll give you a quick runthrough of decorators, and explain, roughly, what metaprogramming is. Take this simple function: :
def add(x, y)::
def add(x, y):This is a decorator function: :
def log(func):The classic way to use the decorator would be: :
def add(x, y)::
@logMoving back onto metaclasses. Let's say we had a class that looked something like: :
class Foobar(object)::
from types import FunctionType:
class Test(object):Phew! Sorry for going on for so long, but this is one of my favourite programming subjects ;) |
wow thanks alot! I have a way better grasp on it now.... One thing though, is it absolutley necessary for the logged function to be nested within log? Can't whats the point of having it nested?
|
Quote:
:
def log(func):I can probably illustrate this better with a simpler example: :
def add(x):For instance: :
>>> increment_by_one = add(1)The log function is similar, but instead of taking a number (x) from the outer function, it takes a function (func). |
Wow. That was definitely a good explanation Arevos. I had tried reading from a tutorial somewhere on the internet earlier, and it didn't explain well or help me very much. This cleared up almost everything for me. You should consider posting this in the tutorial section, or add it to one of the python tutorial threads. :)
|
Thanks for the encouragement, Sane :)
Another nice trick that I found whilst browsing the SQLObject codebase, is that __metaclass__ can be inherited. This can make adding metaclasses to a class somewhat neater: :
class LogMixin(object)::
__metaclass__ = Log |
Ahh, I like that inheritance method. It really helps bundle your code in to logical groups. And it will give you quick control over which functions contain the metaclass, and which do not.
The second method seems like poor form however. Because, if you were writing a program, and you knew that you would need 50 classes that use the metaclass, it sounds like a good idea right? But what if at the end you need an unrelated class to not have a metaclass? You might have screwed yourself over. Perhaps you could add "__metaclass__ = None", I'm not sure. Regardless of that, it doesn't sound like the best way to go. |
If you have 50 classes that need the metaclass I'd assume they'd all be related enough to warrant their own module. This other stray class would not belong in that module. Problem solved
|
| All times are GMT -5. The time now is 12:53 AM. |
Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC