What do you call a class not intended to be instantiated

Terry Reedy tjreedy at udel.edu
Sat Sep 27 19:16:06 EDT 2008


Aaron "Castironpi" Brady wrote:

>>>> class A(type):
> ...     def __call__( self, *ar ):
> ...             print 'call', self, ar
> ...
>>>> class B(object):
> ...     __metaclass__= A
> ...
>>>> B(3)
> call <class '__main__.B'> (3,)
> 
> Overriding the __call__ method of 'type' has the effect of giving you
> a static __call__ method on a class-- a method which doesn't need an
> instance to call.  Your behavior may be counterintuitive though, to
> someone who wants to instantiate 'B', in this case, and proceed like a
> normal object.  That is, they want to call a generic class and use it,
> and also expect instances of B to behave as B.  You can't have both,
> so either return B from B.__new__, or, to instantiate B, take the long
> way and call B.__new__ directly.
> 
>>>> B.__new__(B)
> <__main__.B object at 0x009FDB70>
> 
> Has anyone stepped through the C code to find out when the decision is
> made to call which function, B.__new__ or A.__call__, when B is
> called?  

For Python coded objects, ob(*args) in code translates to internal 
execution of type(ob).__call__(ob, *args) (without further 
translation!).  The interpreter compiles a statement at a time, without 
looking back to do type inferencing, and so does not know what type is 
being called or if it is even callable.

For B, B(*args) == type(B).__call__(B, *args) == A.__call__(B, *args). 
So there is no decision.

For C coded objects, I believe ob(*args) in Python code translate to a C 
call of the C equivalent of type(ob).tp_call (or something like that). 
 From observation, type.tp_call acts something like this:

def __call__(cls, *args):
   if cls == type:
     if len(*args):
       return arg[0].__class__
     elif len(*args) == 3:
       return type.__new__(type, *args) # or maybe not pass type?
     else:
       raise TypeError('type() takes 1 or 3 arguments')
   else:
     return cls.__new__(cls, *args)

So, for a normal class C (an instance of type), type.__call__ calls 
C.__new__.

Terry Jan Reedy





More information about the Python-list mailing list