What do you call a class not intended to be instantiated

B

Bruno Desthuilliers

Aaron "Castironpi" Brady a écrit :
2008/9/22 Bruno Desthuilliers said:
Sounds to me like a functor, aka a function object:
http://en.wikipedia.org/wiki/Function_object
Ok, then the simple solution is to implement a callable type (__call__
method), possibly with appropriate support for the descriptor protocol if
it's meant to be usable as a method.
Yes -- and instantiate the thing and keep the state in the instance,
rather than keeping the state in the class, so that it's possible to
safely have more than one of them if a later design change calls for
it (probably what led people off onto the sidetrack of thinking a
singleton was called for). That's the classic way of implementing a
"class [to be] used as a function".

I think you are either looking for a class that has a generator, or a
generator that has a reference to itself.

???

Going back to robot-mode, Aaron ?
 
A

Aaron \Castironpi\ Brady

Aaron "Castironpi" Brady a écrit :


2008/9/22 Bruno Desthuilliers <[email protected]>:
Sounds to me like a functor, aka a function object:
http://en.wikipedia.org/wiki/Function_object
Ok, then the simple solution is to implement a callable type (__call__
method), possibly with appropriate support for the descriptor protocol if
it's meant to be usable as a method.
Yes -- and instantiate the thing and keep the state in the instance,
rather than keeping the state in the class, so that it's possible to
safely have more than one of them if a later design change calls for
it (probably what led people off onto the sidetrack of thinking a
singleton was called for).  That's the classic way of implementing a
"class [to be] used as a function".
I think you are either looking for a class that has a generator, or a
generator that has a reference to itself.

???

Going back to robot-mode, Aaron ?

Not getting the same sense of "soul" as from my usual posts. I guess
so. Might even drop the name change, too... while I'm at it. One
more word from you about it and I'm starting a thread, and calling it,
"Python and my sense of 'soul'". Ha ha.
 
B

Bruno Desthuilliers

Aaron "Castironpi" Brady a écrit :
On Sep 22, 2:38 pm, Bruno Desthuilliers


Not getting the same sense of "soul" as from my usual posts. I guess
so. Might even drop the name change, too...

Don't !-)
while I'm at it. One
more word from you about it and I'm starting a thread, and calling it,
"Python and my sense of 'soul'". Ha ha.

Please bear with me - and understand that the above half-backed
half-joke was also an implicit aknowledgement of the recent changes in
your mode of communication. I should have added a <wink>, I think...
 
A

Aaron \Castironpi\ Brady

Aaron "Castironpi" Brady a écrit :



Don't !-)


Please bear with me - and understand that the above half-backed
half-joke was also an implicit aknowledgement of the recent changes in
your mode of communication. I should have added a <wink>, I think...

I can attribute it to a change in environment. Going "back" to robot
mode would imply one wasn't always in it, and as such I interpreted a
tacit compliment. Thank you for the compliment, Bruno. I don't
suppose "starting a thread" is much of a threat, after all... at least
in isolation.

Regardless, as I've stated, I find the feedback valuable that there
seems (to people) to be more than one context that I'm writing from,
and I appreciate the chance to learn about it. It's an observation an
erst friend made once that one can never perceive oneself directly.
(Whether that's a virtue depends on what difference there is between
self-conscious, and self-aware.)
 
S

Steven D'Aprano

On 22 Sep 2008 09:07:43 GMT, Steven D'Aprano

Snce when are "users" ever involved
in programming problems or programming languages ?

What an astounding question.

Consider a class. There are the programmers who write the class, and
there are the programmers (possibly the same people, but not necessarily)
who use the class. The second set of people, the programmers who use the
class, are *users* of the class. What else would they be?
 
A

Aaron \Castironpi\ Brady

What an astounding question.

Consider a class. There are the programmers who write the class, and
there are the programmers (possibly the same people, but not necessarily)
who use the class. The second set of people, the programmers who use the
class, are *users* of the class. What else would they be?

Usegrammers?
 
C

Craig Allen

Snce when are "users" ever involved
in programming problems or programming
languages ?

since the begining, the first users are programmers, users of your
libraries.
 
A

Aahz

A wasted definition... The same functionality is achieved by just
creating and importing a module. Your "class methods" would just be
functions within the module; class level attributes would be module
level objects (access with global if writing to them, use a _ to
indicate "internal")

Seems to me that if all the module is used for is to store state, you're
wasting a file on disk. I personally prefer to use a class singleton.
 
S

Steven D'Aprano

Seems to me that if all the module is used for is to store state, you're
wasting a file on disk. I personally prefer to use a class singleton.

I don't recognise the term "class singleton". Can you explain please? How
is it different from an ordinary singleton?

For the record, I ended up deciding that I didn't need any special
objects or metaclass programming, just a factory function which returned
a regular instance. But reading the thread has been a good education for
me, thanks folks.
 
A

Aahz

I don't recognise the term "class singleton". Can you explain please? How
is it different from an ordinary singleton?

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).
 
S

Steven D'Aprano

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).

Amazing. That's *exactly* what I was thinking of when I first asked my
question.

Since I now no longer think I need such a beast, this is just academic
curiosity, but given a class singleton, I'd like to be able to call it as
if it were a function. Normally calling a class object returns an
instance -- I wish to return something else. Is that just a matter of
overriding __new__?

This seems to works:
.... thing = (0, 1, 2)
.... def __new__(cls, *args):
.... return len(args+cls.thing)
....8



Is it really that easy?
 
S

Steven D'Aprano

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.


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:

... thing = (0, 1, 2)
... def __call__(self, *args):
... return len(args + self.thing) ...
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:
.... thing = (0, 1, 2)
.... @classmethod
.... def __call__(cls, *args):
.... return len(args + cls.thing)
....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/
 
A

Aaron \Castironpi\ Brady

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:

...     thing = (0, 1, 2)
...     @classmethod
...     def __call__(cls, *args):
...         return len(args + cls.thing)
...>>> appendor = CallableAppendor()
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.
.... 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? I'm happy that overriding type.__call__ produced the intended
results; it's always nice when things go right.
 
A

Aahz

Where is this "class singleton" terminology from? 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 remember where I picked it up, probably here some years ago.
The point of the terminology is to distinguish how the class is *used*,
in precise parallel with "module singleton".
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.

Absolutely agreed with your first clause, disagreed about the second
clause. As I said earlier, the main point of a class singleton is to get
the effect of a module singleton without the need to create another file
on disk. In that case there is no instance and therefore the point of
the class is no longer to define behavior for instances.

But you can't call a module, and classes have well-defined behavior for
calling them, so you shouldn't try to pervert a class singleton by
defining behavior for calling them. In fact, I would recommend creating
an __init__() method that raises NotImplementedError precisely to prevent
this usage (or have a __new__() method that returns None, but I generally
prefer to recommend practices that work with classic classes).

One cute reason to prefer class singletons to module singletons is that
subclassing works well for creating multiple singletons. But really,
the main reason I use class singletons is that they are the absolute
simplest way to get attribute access:

class Foo: pass
Foo.bar = 'xyz'
if data == Foo.bar:
print "!"

Once it gets much more complicated than that, I prefer to use a smarter
object.
 
R

Roy Smith

[email protected] (Aahz) said:
One cute reason to prefer class singletons to module singletons is that
subclassing works well for creating multiple singletons. But really,
the main reason I use class singletons is that they are the absolute
simplest way to get attribute access:

class Foo: pass
Foo.bar = 'xyz'
if data == Foo.bar:
print "!"

I've often done something similar, creating a dummy class:

class Data:
pass

just so I could create instances of it to hang attributes off of:

foo = Data()
foo.bar = 'xyz'

That's a trick I've been using since the Old Days (i.e. before new-style
classes came along). When I saw your example, my first thought was "That's
silly, now that there's new-style classes, you can just create an instance
of object!". Unfortunately, when I tried it, I discovered it didn't work.
You *can* instantiate object, but you don't get a class instance, so you
can't create attributes on it.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'
 
T

Terry Reedy

Aahz said:
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.

Absolutely agreed with your first clause, disagreed about the second
clause. As I said earlier, the main point of a class singleton is to get
the effect of a module singleton without the need to create another file
on disk.

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

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

tjr
 
T

Terry Reedy

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
 

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
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top