osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

singleton ... again


On Thu, 13 Feb 2014 14:07:55 +1100, Ben Finney wrote:

> Steven D'Aprano <steve at pearwood.info> writes:
> 
>> On Wed, 12 Feb 2014 23:04:32 +1300, Gregory Ewing wrote:
>> > If you really want to make sure nobody creates another instance by
>> > accident, delete the class out of the namespace after instantiating
>> > it.
>>
>> That does not work. It is trivial to get the type from an instance [by
>> calling ?type(foo)?].
> 
> Right, but surely you don't think people would do that ?by accident?,
> which is what Gregory was addressing.

Of course it can happen by accident. It's happened to me, where I've 
accidentally called NoneType() (which raises, rather than returning a new 
instance).

The way it happened is I had a bunch of numeric values, all of the same 
type, and wanted to test that summing them with a custom sum function 
would give the same result whether I provided a start parameter or not:

for data in list_of_datas:
    T = type(data[0])
    zero = T()
    assert sum(data) == sum(data, zero)


only somehow one of the data sets ends up containing None due to another 
bug. Now in *this* case, the error was obvious: NoneType() raises an 
exception. If the type happened to be bool(), I would have been okay too, 
because bool() returns the appropriate singleton True instance.

Because I was testing a function with no side-effects, it wouldn't have 
mattered even if I had accidentally created a extra instance of something 
which nominally ought to have been a singleton. But if I were testing a 
function with side-effects, say one which modifies the internal state of 
the singleton, then I could have been in all sorts of strife.

If you're going to have a singleton, you ought to do one of two things:

* calling the constructor returns the same singleton each time; or

* calling the constructor (apart from the very first time) raises an
  exception.


I prefer the first case.



-- 
Steven