Emulating Final classes in Python

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Jan 17 02:32:53 EST 2017


On Tuesday 17 January 2017 18:05, Steven D'Aprano wrote:

> I wish to emulate a "final" class using Python, similar to bool:
[...]
> Any hints?

I may have a solution: here's a singleton (so more like None than bools) where 
instantiating the class returns the singleton, and subclassing the class fails:



class DoneMeta(type):
    _final = None
    def __new__(meta, name, bases, ns):
        if meta._final is None:
            meta._final = cls = super().__new__(meta, name, bases, ns)
            return cls
        elif meta._final in bases:  # Not sure this check is needed.
            raise TypeError('base class is final and cannot be subclassed')


class DoneType(metaclass=DoneMeta):
    __slots__ = ()
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = inst = super().__new__(cls)
            return inst
        return cls._instance
    def __repr__(self):
        return '<DONE>'


DONE = DoneType()

del DoneType, DoneMeta
assert type(DONE)() is DONE



Thoughts? Any improvements or criticism? (Apart from "don't do it" :-)


Of course this is Python, and so we can actually dig under the hood and make a 
new instance if we really try:

py> x = object.__new__(type(DONE))
py> x
<DONE>
py> x is DONE
False


and similarly there are probably ways to bypass the anti-subclassing code. But 
the way I see it, if you're doing that, you either know what you're doing in 
which case good on you, or you don't, in which case you deserve whatever 
happens to you :-)



-- 
Steven
"Ever since I learned about confirmation bias, I've been seeing 
it everywhere." - Jon Ronson



More information about the Python-list mailing list