What do you call a class not intended to be instantiated

A

Aaron \Castironpi\ Brady

Aaron said:
...     def __call__( self, *ar ):
...             print 'call', self, ar
...
...     __metaclass__= A
...
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.
<__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

Oh, I see. Then it's the class statement that calls type.__new__.

class A: ...
-> A= type( 'A', ... )
-> A= type.__call__( type, 'A', ... )
-> A= type.__new__( type, 'A', ... )

Plus an iteration over the contents of 'namespace', to search for
properties that themselves have a __get__ method. And returns an
unboundmethod instance "of" it, for a value of "of" that's hard to
concentrate on. I jest.

Perhaps what Steven is looking for is a subclass of 'type' that does
not give this default behavior of 'unboundmethoding' everything it
can. That is, defaulting to 'staticmethod' or 'classmethod', and
perhaps offering a 'boundmethod' decorator for the exceptions.

For the case of '__call__', which he does want to control, that could
merely call B.__call__, instead of B.__new__. Untested:
.... def __call__( self, *ar ):
.... return self.__call__( *ar )

or

.... return self.__call__( self, *ar )

Which would come through to 'B' as:
.... __metaclass__= A
.... def __call__( cls, *ar ).

This is because self == B in the example. This makes me scowl. Very
odd.
 
S

Steven D'Aprano

In 3.0, at least, one does not need a disk file to create a module.

2

Seems to work for Python 2.5 as well.

That said, a blank class is even easier, and the representation is
better.

And modules aren't callable. I've often thought they should be.
 
T

Terry Reedy

Steven said:
And modules aren't callable. I've often thought they should be.

Modules are not callable because their class, module, has no __call__
instance method. But (in 3.0, which is all I will check) you can
subclass module and add one.
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__'] def __call__(self, *args, **kwds):
print(self, args, kwds)

<module 'mod' (built-in)>

So, roll your own to your taste.

Terry Jan Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top