What do you call a class not intended to be instantiated

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Sep 27 06:33:44 EDT 2008


On Sat, 27 Sep 2008 18:20:17 +1000, Ben Finney wrote:

> Steven D'Aprano <steve 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?


> It seems redundant to
> me. It also doesn't seem to have anything to do with what "singleton"
> means as a pattern; "using a class" is simply using a class.


I don't see why this idiom causes such conceptual difficulty. There are 
classes with many instances; there are classes with a single instance 
(Singleton). Why should't there be classes with no instances?

A class is just an object. If you find yourself caring whether a 
particular object is a class, an instance or a function, then you have to 
ask yourself why you are worrying about the implementation details. Of 
course as the library writer, it's your job to worry about the 
implementation details, but ideally the library user shouldn't have to.

 
>> Since I now no longer think I need such a beast
> 
> That's a relief :-)
> 
>> I'd like to be able to call [a class] as if it were a function.
>> Normally calling a class object returns an instance -- I wish to return
>> something else.
> 
> In that case, you *don't* want a class at all; the entire point of a
> class is to define behaviour for instances.

Classes encapsulate state + behaviour in one package, and they allow 
inheritance. That's a lot more than merely defining behaviour of 
instances. Instances in turn have the additional capability of being able 
to over-ride the class' state and behaviour:

class C(object):
    x = 'spam'

c = C()
c.x = 'ham'  # doesn't touch C.x

If your instance doesn't do something the class can't do on it's own, why 
bother with the instance?



> Instead, you want to define a class whose *instances* are callable, by
> defining the '__call__' method to do whatever it is you want.

Most of the time, sure.


 
>> This seems to works:
>> 
>> >>> class ClassSingleton(object):
>> ...     thing = (0, 1, 2)
>> ...     def __new__(cls, *args):
>> ...             return len(args+cls.thing) ...
>> >>> ClassSingleton(1, 2, 4, 8, 16)
>> 8
> 
> Horribly obfuscatory. Calling a class should return a new instance of
> the class or something like it.

Apart from the name, which I dislike, what is obfuscatory about it? 
Haven't you ever used factory functions or class builders? It's the same 
principle. Why do you care that ClassSingleton is a class instead of a 
function?

I'm certainly not saying that we should use classes this way all the 
time, but the capability is there, and apparently not by accident. Guido 
wrote:

"__new__ must return an object. There's nothing that requires that it 
return a new object that is an instance of its class argument, although 
that is the convention. If you return an existing object of your class or 
a subclass, the constructor call will still call its __init__ method. If 
you return an object of a different class, its __init__ method will not 
be called."

http://www.python.org/download/releases/2.2.3/descrintro/



> Instead, define it so the user instantiates the class by calling the
> class, and *then* calls that non-class object, and so shouldn't expect
> to get a new instance back:
> 
>     >>> class CallableAppendor(object):
>     ...     thing = (0, 1, 2)
>     ...     def __call__(self, *args):
>     ...         return len(args + self.thing) ...
>     >>> appendor = CallableAppendor()
>     >>> appendor(1, 2, 4, 8, 16)
>     8


That's the right solution when the instance is able to override the state 
and/or behaviour of the class. Most uses of classes are like that:

class Spam(object):
    def __init__(self, n):
        self.n = n
    def sing(self):
        return "spam "*self.n + " glorious SPAM!!!"

Because the behaviour (method 'sing') depends on state which is specific 
to the instance (attribute 'n'), it is right and proper to instantiate 
the class. The class 'Spam' is a constructor for instances, and the 
instances do all the work.

But my earlier example is not the same. In the example I gave, neither 
the behaviour nor the state depend on the instance: everything is 
specified in the class. Ben's variant behaves differently: the caller 
might override appendor.thing by hand. That is Ben's choice, of course, 
and it may be a valid one for many applications, but it's displaying 
different behaviour to my example.

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 concede that this is a made-up example, but here's an actual practical 
example of a class with no instances: Guido's attempt at an Enum:

"This (ab)uses the class syntax as an elegant way to define enumerated 
types. The resulting classes are never instantiated -- rather, their 
class attributes are the enumerated values. For example: 
class Color(Enum):
    red = 1
    green = 2
    blue = 3
print Color.red

 will print the string ``Color.red'', while ``Color.red==1'' is true, and 
``Color.red + 1'' raise a TypeError exception."

http://www.python.org/doc/essays/metaclasses/




-- 
Steven



More information about the Python-list mailing list