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