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 Gary S. Thompson on March 15, 2007 - 18:29:
Edward d'Auvergne wrote:

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


yes but that isn't the class you need to look at object.__class__ and object.__bases__ and so on resursivley...


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

I beg to disagree, it isn't (however type is ;-)) It does exactly what is says on the packet


if you have class A and class B(A)
and instances a and b thereof

a is an A
and b is an A and a B



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

NO... you have two object ot type Singleton i.e. sub.__base__==singleton it is a singleton as is single.__class__ both can be accepted in the sample place and behave the same way this breaks the contract for anything that is is a singleton. There can only be one instance of singleton within the interpreter. You can never have two singletons which share the same type other than being an 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.


[snip to the chase]

I don't know where to start quite. Chris's explanation is clear (and correct).

If one class derives from another it has an is a or inheritance contract.

An apple is a fruit, a fruit is a fruit and a pear is a fruit. any where you accept a fruit you have to accpet apples pears or straight fruit.

Now the singleton pattern is behavioural not inheritance based. For each class you call a singleton there can only be one instance of that type in memory. So if you can have a print queue singleton there can only ever be __one__ instance of a print queue singleton in memory. i.e. only one memory address is associated with the class print queue. if you subclass print queue to give you say an advanced print queue any object is of type advanced print queue is a print queue and and an advanced print queue all at the same time. now print queue was a singleton and so must advanced print queue be. so again there can only be one memory location associated with type advanced print queue and print queue. If you make an instance of print queue which is not and advanced print queue while you have an instance of advanced print queue in memory you have broken the contract.

Lets take it one step further. Now consider if you sub class print queue again to give a dumb print queue. That object is a print queue and a dumb print queue all at the same time. A print queue is a singleton and so must be a dumb print queue. If you create an object of dumb print queue no other memory location other than that __instance__ may be associated with a print queue or an advanced print queue (which by its inheritance relationsship to print queue has __to be a print queue__) . As soon as you create another isntance of either of these you break the singleton contract because otf the inheritance contract. Except under very strict conditions there is a very big impedance mismatch between singleton and inheritance (which I can go into if need be).

I am pretty secure with my undertanding of inheritance and this pattern and it is just one of those unavoidable thing. If you label something as a singleton and there can only ever be one instance of that type in memory. Anything you call a singleton must be the only instance of that type in memory whehter it is of that type directly or because you can follow an ineritance relationhsip to it.

It would somethimes be nice two have to fermions that could both occupied the same space (ever wanted to walk through a wall when someone was cross at you) but they can't (tip you hat to mr pauli) they just are not made that way and the same goes here!


regards gary



Edward


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

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

This is the relax-devel mailing list
relax-devel@xxxxxxx

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

.



--
-------------------------------------------------------------------
Dr Gary Thompson
Astbury Centre for Structural Molecular Biology,
University of Leeds, Astbury Building,
Leeds, LS2 9JT, West-Yorkshire, UK             Tel. +44-113-3433024
email: garyt@xxxxxxxxxxxxxxx                   Fax  +44-113-2331407
-------------------------------------------------------------------





Related Messages


Powered by MHonArc, Updated Sat Mar 17 02:40:17 2007