[TransWarp] Metaprogramming in Python
Phillip J. Eby
pje at telecommunity.com
Wed Jul 25 14:56:31 EDT 2001
At 04:42 PM 7/25/01 +0200, Dominikus Herzberg (EED) wrote:
> class Port(InterfaceType):
> pass
>
>The fun part is that
>
> >>> type(Port)
>
>results in
>
> <type 'instance'>
>
>Why? I understand that class definitions are an executable statement
>in python. As soon as python passes the class definition Port, python
>first evaluates the inheritance list, here InterfaceType, which should
>evaluate to a class object. In this case, it evaluates to a class
>instance instead! This is clearly the point of where the magic begins
>... but how does it continue. Why does Port finally evaluate to a
>class instance but having typical properties of a class object like
>__dict__ or __bases__? What does Port make this sort of a hybrid
>thing?
It's not a hybrid, it's an instance. Your own code shows why it has
__name__ and __bases__ - after all, they're in the __init__() method. Its
__dict__ is the normal instance dictionary, which is why it has to have a
__dict to represent the class dictionary.
When you do this:
> InterfaceType = InterfaceMetaClass("InterfaceType",(),{})
You're creating an instance of class InterfaceMetaClass. This is *exactly*
the same as what happens when you do this:
> class Port(InterfaceType):
> pass
Basically, if you subclass from an object whose type() or __class__ is
callable, it is called with the arguments (name,bases,dict). In this case
InterfaceType has a __class__ which is callable (InterfaceMetaClass). So
Python does this:
Port = InterfaceMetaClass("Port",(InterfaceType,),{contents of class block
as a dictionary})
Voila. You now have a "class" called Port that is actually another
instance of InterfaceMetaClass. If you subclass Port, you'll end up with
yet another instance of InterfaceMetaClass. And so on.
Now, if you want to create instances of your "class", and you do, say:
foo = Port()
This will call the "__call__" method of the Port instance of your
InterfaceMetaClasss class. So if InterfaceMetaClass defines a __call__
method, whatever it returns will be the "instance" of Port.
If you want to learn more about Python metaprogramming, the
comp.lang.python newsgroup/mailing list, and the www.python.org site are
probably good places to look.
More information about the PEAK
mailing list