edgegraph.structure.singleton.TrueSingleton

edgegraph.structure.singleton.TrueSingleton#

class edgegraph.structure.singleton.TrueSingleton#

Bases: type

Metaclass for true singletons.

See also

The design of this metaclass is taken directly from this excellent StackOverflow answer by user @agf. This answer is also perhaps the clearest explanation of metaclasses I’ve ever seen in the wild. Thanks!!

https://stackoverflow.com/a/6798042

Danger

If you find yourself using this with Vertex, something will probably go wrong. Though it will, technically speaking, work, the effects of true-singleton vertices have little real-world purpose, and their use may have side effects far beyond what you predict. If you think “yes, I really do need a singleton vertex,” it is probably a sign that something else has gone horribly wrong and you should refactor whatever you’re doing.

You may wish to read about semi_singleton_metaclass() for an alternative, less-probably-a-bad-idea approach.

Using this metaclass allows creation of a truly global singleton object. Only one of them can ever be created, observing the following rules:

  1. Instances of such classes can only be created once

  2. instances of such classes will only have their __init__ called once, no matter what arguments (same or different) may be passed in on a future attempt

  3. All attempts to create a new instance of the given class will return the One True Instance

For example:

>>> from edgegraph.structure import singleton
>>> class MySingleton(metaclass=singleton.TrueSingleton):
...     def __init__(self, foo, bar=False):
...         self.foo = foo
...         self.bar = bar
...
>>> s1 = MySingleton(8, True)
>>> s1
<__main__.MySingleton object at 0xdeadbeef>
>>> s2 = MySingleton(8, True)
>>> s2
<__main__.MySingleton object at 0xdeadbeef>
>>> s1 is s2
True
>>> s3 = MySingleton(512, 2**32)
>>> s3
<__main__.MySingleton object at 0xdeadbeef>
>>> s2 is s3
True
>>> s3.foo = 9001
>>> s1.foo
9001
>>> s2.foo = 18002
>>> s3.foo
18002

We can see here that, no matter whether you give the class the same or different arguments, the first-ever instance is always what you get. Note the use of the is operator here – this checks that the two objects given are the same reference, not just of the same value.

Furthermore, changing attributes of the one instance affects all other copies of the singleton floating around, because they’re all shallow references to the original.

__init__(*args, **kwargs)#

Methods

__init__(*args, **kwargs)

mro()

Return a type's method resolution order.

mro()#

Return a type’s method resolution order.