[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