I create several classes to use them as state flags (this is more an exercise, although I will use them in a real project), just like we use None in Python, i.e.
... some_var is None ...
NoneType has several special properties, the most important is singleton, that is, there can be no more than one instance of NoneType during any interpreter session, and its instances ( None objects) are immutable. I came up with two possible ways to implement somewhat similar behavior in pure Python, and I really want to know which one looks better from an architectural point of view.
1. Do not use instances at all.
The idea is to have a metaclass that creates immutable classes. Classes are not allowed to have instances.
class FlagMetaClass(type): def __setattr__(self, *args, **kwargs): raise TypeError("{} class is immutable".format(self)) def __delattr__(self, *args, **kwargs): self.__setattr__() def __repr__(self): return self.__name__ class BaseFlag(object): __metaclass__ = FlagMetaClass def __init__(self): raise TypeError("Can't create {} instances".format(type(self))) def __repr__(self): return str(type(self)) class SomeFlag(BaseFlag): pass
And get the desired behavior
a = BaseFlag a is BaseFlag # -> True a is SomeFlag # -> False
Obviously, any attempt to set attributes for these classes will fail (of course, there are several hacks to overcome this, but the direct path is closed). And the classes themselves are unique objects loaded into the namespace.
2. The correct singleton class
class FlagMetaClass(type): _instances = {} def __call__(cls): if cls not in cls._instances: cls._instances[cls] = super(FlagMetaClass, cls).__call__() return cls._instances[cls]
Here Flag classes are real singletones. This particular implementation does not cause an error when trying to create another instance, but returns the same object (although it is easy to change this behavior). Both classes and instances cannot be directly modified. The point is to create an instance of each class upon import, as was done with None .
Both approaches give me a few immutable unique objects that can be used for comparison just like None . For me, the second one looks more NoneType -like, since None is an instance, but I'm not sure if it costs an increase in ideal complexity. Waiting for you from you.