Monday 7 February 2011

Singleton objects

Singleton objects are not some fancy concept but a very practical solution to representing a specific value as an object as Pythons None object shows.

Many programming languages provide syntactical solutions to provide constants. Literals like 123 or "a string" are almost always constants but if you want to give a meaningful name to a constant you need a different approach.

Referring to value by name is simple enough, after all a variable assignment does just that, but you need some way to indicate that that variable shouldn't be altered after the assignment. Python does not provide a way to specify a constant but there are ways around this, see for example (this recipe).

Paradoxically, it is comparatively simple to define a class that allows only a single instantiated object. There are arguments for and against this Singleton Design Pattern and this article is a good starting point if you want to read about it. And whatever the merits of this design pattern, you can't avoid it because many constants in Python are implemented as singleton classes, for example True, False, NotImplemented and None.

And the None implementation illustrates another practical advantage: when comparing a value against a singleton we can check whether they are identical (with the is operator) instead of comparing their values (with the == operator) and although this might not be the primary purpose, it does give us a clear speed advantage as the next snippets shows:

import timeit

s1 = "123 == None"
s2 = "a == None"
s3 = "123 is None"
s4 = "a is None"

t = timeit.Timer(stmt=s1,setup='a=123')
print (s1, "%.2f usec/pass" % (count * t.timeit(number=count)/count))
t = timeit.Timer(stmt=s2,setup='a=123')
print (s2, "%.2f usec/pass" % (count * t.timeit(number=count)/count))
t = timeit.Timer(stmt=s3,setup='a=123')
print (s3, "%.2f usec/pass" % (count * t.timeit(number=count)/count))
t = timeit.Timer(stmt=s4,setup='a=123')
print (s4, "%.2f usec/pass" % (count * t.timeit(number=count)/count))
The results of running this bit of code on my Samsung NC10 netbook give me the following output:
123 == None 0.29 usec/pass
a == None 0.31 usec/pass
123 is None 0.20 usec/pass
a is None 0.21 usec/pass
This is a significant difference and although it doesn't seem to amount to much, this might shave several seconds of your algorithm when you compare for example the results of a large database query, as databases tend to represent NULL values as None.

1 comment:

  1. This professional hacker is absolutely reliable and I strongly recommend him for any type of hack you require. I know this because I have hired him severally for various hacks and he has never disappointed me nor any of my friends who have hired him too, he can help you with any of the following hacks:

    -Phone hacks (remotely)
    -Credit repair
    -Bitcoin recovery (any cryptocurrency)
    -Make money from home (USA only)
    -Social media hacks
    -Website hacks
    -Erase criminal records (USA & Canada only)
    -Grade change
    -funds recovery

    Email: onlineghosthacker247@ gmail .com