If the base class cannot be a singleton due to the derived class objects
being instances of it, then how can the three different values of 'x'
below be explained?


$ python
Python 2.4.1 (#2, Oct  6 2006, 15:14:48)
[GCC 4.0.1 (4.0.1-5mdk for Mandriva Linux release 2006.0)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from Queue import Queue
>>>
>>> class ThreadQueue(Queue, object):
...     instances = {}
...     def __new__(cls, *args, **kargs):
...         if ThreadQueue.instances.get(cls) is None:
...             ThreadQueue.instances[cls] = object.__new__(cls, *args,
**kargs)
...         return ThreadQueue.instances[cls]
...
>>> class ResultsQueue(ThreadQueue):
...     mf_results = {}
...
>>> class OptimisationQueue(ThreadQueue):
...     min_instances = []
...
>>>
>>> # Create the three singletons.
... thread_queue = ThreadQueue()
>>> results_queue = ResultsQueue()
>>> opt_queue = OptimisationQueue()
>>>
>>> # Show that the singletons have different locations in memory - i.e.
are different instances.
... print id(thread_queue)
1077833228
>>> print id(results_queue)
1077867628
>>> print id(opt_queue)
1077881612
>>>
>>> # Add objects to the singletons.
... thread_queue.x = 1
>>> results_queue.x = 2
>>> opt_queue.x = 3
>>>
>>> # Print the objects of the singletons.
... print thread_queue.x
1
>>> print results_queue.x
2
>>> print opt_queue.x
3
>>>
>>> print results_queue is thread_queue
False
>>> print opt_queue is thread_queue
False
>>> print results_queue is opt_queue
False
>>>
>>> # Instantiate the three singletons again.
... thread_queue2 = ThreadQueue()
>>> results_queue2 = ResultsQueue()
>>> opt_queue2 = OptimisationQueue()
>>>
>>> # Print the objects of the singletons.
... print thread_queue2.x
1
>>> print results_queue2.x
2
>>> print opt_queue2.x
3


Bye,

Edward


On Thu, 2007-03-22 at 11:39 +0000, Chris MacRaild wrote:
> On Thu, 2007-03-22 at 15:09 +1100, Edward d'Auvergne wrote:
> > As far as I'm concerned there is absolutely nothing stopping me in
> > Python from creating a base class with singleton properties and then
> > subclassing this to create independent singletons that I can use for
> > different purposes.  An example of a singleton base class and
> > inheritance could be as follows.  Say I create a base class
> > SingletonQueue that has advanced queuing properties (say to be thread
> > safe) together with the properties of being a singleton.  Then I
> > create ResultsQueue(SingletonQueue) to queue model-free optimisation
> > results coming in from remote machines on a grid (there is only one
> > instance of this queue in the program).  I also create
> > OptimisationQueue(SingletonQueue) which is a queue for each
> > optimisation to be sent out to a grid computer (again there is only
> > one instance of this queue in the program).  These two queues benefit
> > from being thread safe.  Now, what exactly is stopping me from doing
> > this?  And what is stopping me from using SingletonQueue as a third
> > singleton object for a completely unrelated purpose?  What if
> > SingletonQueue was actually named ThreadQueue and was used as a queue
> > of threads awaiting execution?  I could use all these three queues,
> > they would be singletons, and their namespaces will never clash!
> 
> Python has never claimed to be an arbiter of logic, or even of good
> programming practise - just because Python allows you to do it, it
> doesn't mean it makes sense, or that it is a good idea. No-one is
> suggesting there is any impediment to what you describe, except for the
> fact that SingletonQueue is no longer a singleton, because both the
> single instance of ResultsQueue and the single instance of
> OptimisationQueue are also instances of SingletonQueue. You have two
> instances of the same class, therfore the class is not a singleton.
> 
> Here is how to impliment exactly what you describe, without breaking the
> singleton design pattern:
> 
> >>> class AbstractQueue:
> ...     # NOTE: this is NOT a singleton!
> ...     # define a general queue here
> >>> class ResultsQueue(AbstractQueue):
> ...     # modify the default queue for results
> >>> class OptimisationQueue(AbstractQueue):
> ...     # modify the default queue for oplimisations
> >>> ResultsQueue = ResultsQueue()
> >>> OptimisationQueue = OptimisationQueue()
> 
> We have exactly one instance of ResultsQueue and OptimisationQueue, so
> both are singletons, as per the design. AbstractQueue never claimed to
> be a singleton, because it isn't - ResultsQueue and OptimisationQueue
> are both instances of AbstractQueue.
> 
> > 
> > For discussions about inheritance of singletons, see the Python
> > cookbook (http://aspn.activestate.com/ASPN/Cookbook/Python).  Examples
> > include:
> > 
> > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/102187 (see
> > the comments section).
> > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531 (see the
> > comment with the title 'Singletons using new-style classes')
> > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/113657 (this
> > singleton 'behaves well with inheritance')
> 
> Sure, but there are plenty of contradictory statements here too, eg.:
> 
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
> (inheriting singleton vs inheriting borg):
> "What happens in a large system when two separate subsystems both
> inherit from (extend) a singleton-class? It's anything but clear to me
> -- error at runtime, at compiletime, at linktime (none such in Python,
> let's say at import-time), or what behavior...?"
> 
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/465850:
> "One problem introduced here is that inheritance is broken, but that is
> more of a problem of the Singleton pattern than of this recipe."
> 
> 
> The moral: you can find someone on a public message board to support
> almost any opinion.
> 
> 
> 
> > 
> > As for instances of base classes, towards the bottom of the Wikipedia
> > page http://en.wikipedia.org/wiki/Inheritance_(computer_science) there
> > is the text:
> > 
> > "In most quarters, class inheritance for the sole purpose of code
> > re-use has fallen out of favor. The primary concern is that
> > implementation inheritance does not provide any assurance of
> > polymorphic substitutability—an instance of the re-using class cannot
> > necessarily be substituted for an instance of the inherited class. An
> > alternative technique, delegation, requires more programming effort
> > but avoids the substitutability issue."
> > 
> > According to this statement 'an instance of the re-using class' is
> > different to the 'instance of the inherited class'.  The rest of this
> > text is opinion.
> 
> Well, at least you are honest about quoting selectively. Infact
> polymorphism can be rather a headache in many languages, but in this
> respect Python is much beter than most. Of course 'an instance of the
> re-using class' is different to the 'instance of the inherited class',
> but the instance of the re-using class is also an instance of the
> inherited class. ie. there are two classes, two objects, and three
> instance relationships linking the classes with the objects: the one
> object is just an instance of the base class, while the other object is
> an instance of both the base class and the sub-class.
> 
> >   Now according to
> > http://en.wikipedia.org/wiki/Instantiation_(computer_science):
> > 
> > "Instantiation is the process of creating a specific object which is a
> > member or instance of a class."
> > 
> > Hence the instance is a specific object.  As the specific object lies
> > at a specific point in memory space, then if two variables point to
> > the same instance then the Python the 'id()' function will return the
> > same number.  According to that function's docstring:
> 
> One subtle point that might help here - 'instance' refers first to a
> relationship, it is only a conventional shorthand that allows us to say
> 'the instance is an object'. Instance is a non-exclusive relationship
> between two objects, so there can be many instance relationships between
> only a few objects. This can lead to confusion if we take too litteraly
> the 'instance is an object' type shorthand and try to generate a
> one-to-one correspondence between instancehood and object. 
> 
> > 
> > Help on built-in function id in module __builtin__:
> > 
> > id(...)
> >     id(object) -> integer
> > 
> >     Return the identity of an object.  This is guaranteed to be unique among
> >     simultaneously existing objects.  (Hint: it's the object's memory 
> > address.)
> > 
> > To demonstrate this, try importing the 'singleton_inheritance' module
> > attached to my message at
> > https://mail.gna.org/public/relax-devel/2007-03/msg00077.html (the
> > text at the very bottom) and running the id() functions on the two
> > singletons:
> > 
> > relax> import singleton_inheritance
> > 
> > Singleton is NewSingleton: False
> > Contents of Singleton:    ['__doc__', '__init__', '__module__', 'a',
> > 'base_fn', 'x']
> > Contents of NewSingleton: ['__doc__', '__init__', '__module__', 'a',
> > 'base_fn', 'new_fn', 'x', 'y']
> > Singleton.base_fn is NewSingleton.base_fn: False
> > 
> > Singleton.a:    1
> > NewSingleton.a: -1
> > Singleton.x:    2
> > NewSingleton.x: 3
> > 
> > Singleton.base_fn():
> > Hello
> > NewSingleton.base_fn():
> > Hello
> > NewSingleton.new_fn():
> > Bye
> > relax> id(singleton_inheritance.Singleton)
> > 1080385452
> > relax> id(singleton_inheritance.NewSingleton)
> > 1083092716
> > 
> > These are two different memory addresses.  Hence these are two
> > different objects.  They are also 'simultaneously existing objects'.
> > As an instance is a specific object, and here with have two specific
> > objects, we have two instances.  QID!
> 
> QID what? You have convinsingly demonstrated that two different objects
> are indeed two different objects. This has no bearing on whether they
> share instance relationships with the base class. Indeed the fact that
> the are two different objects is exactly why they breach the singleton
> design of the base class.
> 
> 
> Chris
> 
> 
> > 
> > Bye,
> > 
> > Edward
> > 
> > 
> > On 3/22/07, Chris MacRaild <[EMAIL PROTECTED]> wrote:
> > > On Sat, 2007-03-17 at 12:27 +1100, Edward d'Auvergne wrote:
> > > > The attached file is a Python module, try importing it and then
> > > > playing with its contents.  The module contains two singletons -
> > > > 'Singleton' and 'NewSingleton'.  Both are instantiated in the same
> > > > manner as new relax data storage object (implementation B which we
> > > > voted for), the class name being masked by the instance reference.
> > > > NewSingleton is derived from the Singleton base class demonstrating
> > > > inheritance.  QID!
> > > >
> > > > These singletons are two completely different objects (in different
> > > > memory space) which can be used for completely different tasks and can
> > > > be used by completely different parts of the program all while being
> > > > true singletons - only one instance of each will ever exist in the
> > > > program.  If you cannot see this, I challenge you to write a counter
> > > > example module demonstrating that what this extremely basic module is
> > > > doing cannot be done.
> > >
> > > What this module is doing can be done (of course), but it breaks the
> > > Singleton design because:
> > >
> > > >>> isinstance(NewSingleton, Singleton.__class__)
> > > True
> > >
> > > Contrary to your previous assertions, isinstance is aptly named, and
> > > correctly identifies the inheritance relationship between these two
> > > objects. In other words, because NewSingleton inherits from
> > > Singleton.__class__ (ie. the class, not the instance of the same name),
> > > NewSingleton is an instance of Singleton.__class__
> > >
> > > This is fundamental to the nature of inheritance, and is the basis of
> > > our dissagreements. Again, the classic inheritance metaphor: class Apple
> > > is a subclass of the class Fruit, and GrannySmith is a subclass of the
> > > Apple. Your argument that an object cannot be an instance of more than
> > > one class flies in the face of reason - quite clearly, any object which
> > > is an instance of the class GrannySmith, is also an instance of Apple
> > > and of Fruit. This is essential to the nature of sub-classing, in both
> > > common logic and in OO programing.
> > >
> > > Perhaps it is helpful to consider the distinction between Inheritance
> > > and Delegation. Both achieve similar things in terms of code reuse and
> > > behavioural modification, but they do so in quite different ways, and
> > > have important functional differences. Given some base class with lots
> > > of methods that I want to access, while making a few changes:
> > >
> > > >>> class Base:
> > > ...     def methodA(self):
> > > ...         print "A"
> > > ...     def methodB(self):
> > > ...         print "B"
> > > ...     # lots more methods...
> > >
> > > I could inherit from Base, and change the functionality:
> > >
> > > >>> class Inherited(Base):
> > > ...     def methodA(self):
> > > ...         print "a\n"
> > >
> > > Or I could delegate to Base those methods that I don't redefine:
> > >
> > > >>> class Delegated:
> > > ...     def methodA(self):
> > > ...         print "a\n"
> > > ...     def __getattr__(self, attr):
> > > ...         # If attribute lookup fails, delegate to Base
> > > ...         return getattr(Base(), attr)
> > >
> > > Instances of the two classes, Inherited and Delegated, are functionally
> > > very similar: they have all of the same methods, most of which are
> > > identical to those of Base. There is one important difference:
> > >
> > > >>> isinstance(Inherited, Base)
> > > True
> > > >>> isinstance(Delegated, Base)
> > > False
> > >
> > > A great example of inheritance in the sense I am describing comes from
> > > the Python exceptions system. All python exceptions are an instance of
> > > the base class Exception, and from there ther exists a hierachy of
> > > exceptions: ArithmeticError is a subclass of Exception, and in turn is a
> > > base class for all of the standard maths errors (OverflowError,
> > > ZeroDivisionError, etc); likewise LookupError derives from Exception,
> > > and is base class for KeyError and IndexError. This hierachy is very
> > > powerful, because it allows us to handle different types of error in
> > > different ways:
> > >
> > > >>> try:
> > > ...     errorProneFunction(args)
> > > ... except LookupError:
> > > ...     dealWithLookupError(args)
> > > ... except ArithmeticError:
> > > ...     dealWithArithmeticError(args)
> > > ... except:
> > > ...     # All other errors
> > > ...     dealWithOtherError(args)
> > >
> > > Suppose there is a case that I want to catch as an exception, that is
> > > maths-related. Although it is not one of the standard maths errors, I
> > > want to handle it in the same way (with the function
> > > dealWithArithmeticError() ). I simply need to subclass from
> > > ArithmeticError:
> > >
> > > >>> class MyMathsError(ArithmeticError):
> > > ...     pass
> > >
> > > This works because an exception which is an instance of MyMathsError is
> > > also an instance of ArithmeticError, so the statement except
> > > ArithmeticError will catch MyMathsError, as well as OverflowError,
> > > ZeroDivisionError and the rest. Importantly, no amount of delegation
> > > will make this work:
> > >
> > > >>> class AnotherMathsError:
> > > ...     def __getattr__(self, attr):
> > > ...         # If attribute lookup fails, delegate to Base
> > > ...         return getattr(ArithmeticError(), attr)
> > >
> > > AnotherMathsError is not caught by except ArithmeticError, because it
> > > lacks the requisite inheritance relationship - it is not an instance of
> > > ArithmeticError.
> > >
> > > So, to restate what I think is the orthodox OO understanding of
> > > inheritance: any object which is an instance of a sub-class S is also an
> > > instance of all of the classes which are base-classes of S. This is
> > > stated somewhat obtusely at http://en.wikipedia.org/wiki/Inheritance_%
> > > 28computer_science%29 in the second paragraph:
> > >
> > > "Inheritance is also sometimes called generalization, because the is-a
> > > relationships represent a hierarchy between classes of objects. For
> > > instance, a "fruit" is a generalization of "apple", "orange", "mango"
> > > and many others. One can consider fruit to be an abstraction of apple,
> > > orange, etc. Conversely, since apples are fruit (i.e. an apple is-a
> > > fruit), apples may naturally inherit all the properties common to all
> > > fruit, such as being a fleshy container for the seed of a plant."
> > >
> > > and (similarly obscurely) in almost all basic descriptions of Object
> > > Orientated coding. This is critically important, because it allows
> > > client code to use instances of the sub-class as if they were instances
> > > of the base-class, without knowing anything about the properties (or
> > > even the existance) of the sub-class.
> > >
> > > Chris
> > >
> > >
> > >
> > >
> > >
> > 
> 


_______________________________________________
relax (http://nmr-relax.com)

This is the relax-devel mailing list
[email protected]

To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-devel

Reply via email to