mailRe: Vote for the design of the relax data storage object singleton.


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by Edward d'Auvergne on March 15, 2007 - 17:21:
On 3/16/07, Chris MacRaild <c.a.macraild@xxxxxxxxxxx> wrote:
On Fri, 2007-03-16 at 01:50 +1100, Edward d'Auvergne wrote:
> On 3/16/07, Chris MacRaild <c.a.macraild@xxxxxxxxxxx> wrote:
> > On Fri, 2007-03-16 at 01:00 +1100, Edward d'Auvergne wrote:
> > > On 3/15/07, Chris MacRaild <c.a.macraild@xxxxxxxxxxx> wrote:
> > > > On Thu, 2007-03-15 at 00:09 +1100, Edward d'Auvergne wrote:
> > > > > On 3/14/07, Chris MacRaild <c.a.macraild@xxxxxxxxxxx> wrote:
> > > > > > On Tue, 2007-03-13 at 19:51 +1100, Edward d'Auvergne wrote:
> > > > > > > Gary,
> > > > > > >
> > > > > > > I've written some unit tests which are located in the file
> > > > > > > 'test_suite/unit_tests/data/__init__.py'.  Would you know what
> > > > > > > modifications I need to apply to make these tests run?  These 
tests
> > > > > > > are for the methods of the Data singleton class (the relax data
> > > > > > > storage object) which is located in 'data/__init__.py'.  I 
haven't
> > > > > > > used the statement 'from x import Data' for this class so it is 
the
> > > > > > > legal and ubiquitous usage of an __init__.py file.  Would
> > > > > > > 'unit_test_runner.py' handle this code?
> > > > > > >
> > > > > > > Thanks,
> > > > > > >
> > > > > > > Edward
> > > > > > >
> > > > > > >
> > > > > > > P.S.  These tests demonstrate the utility of subclassing the 
singleton
> > > > > > > and is one reason I was arguing for the use of the class import 
rather
> > > > > > > than reference import.
> > > > > > >
> > > > > >
> > > > > > It is of course correct that the Singleton implimentation I 
proposed
> > > > > > does not allow for subclassing. This however might well be seen 
as a
> > > > > > design feature, given the well known conceptual problems with
> > > > > > subclassing Singleton. Essentially, subclassing violates the 
Singleton
> > > > > > Design Pattern:
> > > > > >
> > > > > > class Singleton:
> > > > > >     def __new__(self):
> > > > > >         ...
> > > > > >
> > > > > > class Sub(Singleton): pass
> > > > > >
> > > > > > >>> a = Singleton()
> > > > > > >>> b = Sub()
> > > > > > >>> isinstance(a,Singleton)
> > > > > > True
> > > > > > >>> isinstance(b,Singleton)
> > > > > > True
> > > > > > >>> a is b
> > > > > > False
> > > > > > >>> a == b
> > > > > > False
> > > > > >
> > > > > > ie. we have 2 instances of Singleton that are not the same thing, 
and
> > > > > > not even equal! If this is the behaviour you want, then you need
> > > > > > something other than Singleton. On the other hand, if you really 
want
> > > > > > Singleton, then you can't also hope for subclassability.
> > > > >
> > > > > Actually one is an instance of Singleton and the other is an 
instance
> > > > > of Sub.
> > > >
> > > > The definition of inheritance is that an instance of the subclass is
> > > > also an instance of the parent class. ie. b is an instance of both Sub
> > > > and Singleton. Inheritance from a Singleton class is therefore a 
logical
> > > > contradiction.
> > >
> > > That is actually incorrect!
> >
> > Sorry to drag this on, but I'm not incorrect here, and its a fairly
> > fundamental point of OO philosophy and practice that is well worth
> > getting right. This is pasted directly from my Python command line (the
> > interpreter does not lie!):
> >
> > >>> class A: pass
> > ...
> > >>> class B(A): pass
> > ...
> > >>> a= A()
> > >>> b = B()
> > >>> isinstance(a,A)
> > True
> > >>> isinstance(a,B)
> > False
> > >>> isinstance(b,B)
> > True
> > >>> isinstance(b,A)
> > True
> >
> > Because B is a subclass of A, all instances of B are also instances of A
>
> The 'isinstance()' built-in function will return true if object x is
> an instance of the supplied class or, importantly, a subclass.  This
> is what it's docstring says.  Try the following instead (after
> reissuing the above statements):
>
> >>> a is b
> False
> >>> hash(a)
> -1217311764
> >>> hash(b)
> -1214788020
> >>> id(a)
> -1217311764
> >>> id(b)
> -1214788020
>
> If b was the same instance as a, then the first statement would return
> true.  The two hash() statements show that a and b are different.  The
> two id() statements show that they occupy different locations in
> memory - the number is the object's memory address.  Another test is
> populating the empty containers:
>
> >>> a.x = 1
> >>> b.y = 2
> >>> dir(a)
> ['__doc__', '__module__', 'x']
> >>> dir(b)
> ['__doc__', '__module__', 'y']
>
> The instances a and b are very much different!

This is all true, but misses the point. a and b are different objects,
but they are of the same type:

>>> type(a) is type(b)
True

They are necessarily the same type, both are <type 'instance'>.

and both of them are instances of the parent class A. So to go back to
where we started: for almost any implimentation of Singleton

Both are not instances of A. The Python builtin function 'isinstance()' is poorly named. It returns True if object b is an instance of class B. But it also returns true if object b is an instance of class B which is subclassed from A (isinstance(b, A)). Note that there is no reference to an instance of A in this second test, either here or when typing 'help(isinstance)').


>>> single = Singleton()
>>> class Sub(Singleton): pass
...
>>> sub = Sub()
>>> isinstance(sub,Singleton)
True

This is the second part of the isinstance test, seeing if sub is and instance of some class which is itself subclassed from Singleton.


>>> isinstance(single,Singleton)
True

This is the first part of the isinstance test, the actual testing if it is an instance.


>>> sub is single
False

This breaches the Singleton design because we have two *different*
objects that are both instances of the Singleton class.

WRONG!!! We now have two different singletons! They occupy different memory addresses and will have different contents. For example one dictionary type can be the relax data storage object and the other can be an object storing the various components used in the chi-squared equation, relaxation equations, spectral density values, and geometric components all calculated by the module 'maths_fns.mf'. Both these two objects benefit by being singletons - the alternative currently used by 'maths_fns.mf' is to pass a single data object into the hundreds of functions which use that object.


To put this in terms of the favourite metaphore, because apple is a
subclass of fruit, all apples are also fruits (ie. all instances of
class Apple in also instances of class Fruit). Even if you have several
different apples, this does not make them any less fruity.

True it is a fruit, but it isn't the fruit object. To place this subclassing into this type of context, we could create a dictionary type singleton and then subclass both the relax data storage object and any new objects from this single base class. Then both objects are side by side on this inheritance tree with the ancestral singleton base class at the bottom of the tree. This inheritance pattern is useful if one object is more than just a subset of the other. However if you are happily using the Fruit object in your program and would like to add support for Apples, there is no need for this branching pattern. Simply subclass Fruit and add the additional features required for the Apple.


Instance refers to a non-exclusive relationship between class and
object: many different objects can be instances of the same class

In this case the different objects are different instances of the same class, they are located in different parts of the memory.

and
any one object can be an instance of many different classes.

There I completely disagree.

Inheritance
is the mechanism of this non-exclusivity; Singlton seeks to limit it.
Hence the two are incompatible when applied to the same object.

The concept of the Singleton and the concept of Inheritance are in no way related and are perfectly compatible with each other. Singletons can have Inheritance. Classes, which can be inherited, can also be singletons.

Edward


P.S. For those still following this thread, this argument is not related to what was voted upon :)



Related Messages


Powered by MHonArc, Updated Thu Mar 15 18:40:17 2007