What do you call a class not intended to be instantiated

Aaron "Castironpi" Brady castironpi at gmail.com
Sat Sep 27 08:39:59 EDT 2008


On Sep 27, 5:33 am, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> On Sat, 27 Sep 2008 18:20:17 +1000, Ben Finney wrote:
> > Steven D'Aprano <st... at REMOVE-THIS-cybersource.com.au> writes:
>
> >> On Fri, 26 Sep 2008 22:15:43 -0700, Aahz wrote:
> >> > An ordinary singleton is instantiating the class multiple times yet
> >> > returning the same instance object; a class singleton is simply using
> >> > the class directly (like a module).
>
> > Where is this "class singleton" terminology from?
>
> I don't know. Googling on it brings up an awful lot of C++ and Java
> source code for regular Singletons. Perhaps Aahz can shed some light on
> it?

[snip]

> In my example, the instance doesn't matter. I could write it like this:
>
> >>> class CallableAppendor(object):
>
> ...     thing = (0, 1, 2)
> ...     @classmethod
> ...     def __call__(cls, *args):
> ...         return len(args + cls.thing)
> ...>>> appendor = CallableAppendor()
> >>> appendor.thing = (1, 2, 3, 4, 5, 6, 7, 8)
> >>> appendor(1, 2, 4, 8, 16)
> 8
> >>> CallableAppendor.__call__(1,2,4,8,16)
>
> 8
>
> but what's the purpose of instantiating the class?

I've used them (class singletons, adopting the term) as a Globals
namespace, but only to the end of tidying.  It makes it easy to
reassign immutables.

It is too bad 'CallableAppendor.__call__(1,2,4,8,16)' doesn't work as
expected.  That is, 'CallableAppendor(1,2,4,8,16)' dosen't call
'__call__'.  I have a workaround, which may be just what you're
looking for.

>>> 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?  I'm happy that overriding type.__call__ produced the intended
results; it's always nice when things go right.



More information about the Python-list mailing list