Emulating Final classes in Python
steve+python at pearwood.info
Tue Jan 17 18:51:03 EST 2017
On Wed, 18 Jan 2017 06:14 am, Ethan Furman wrote:
> On 01/16/2017 11:32 PM, Steven D'Aprano wrote:
>> On Tuesday 17 January 2017 18:05, Steven D'Aprano wrote:
>>> I wish to emulate a "final" class using Python, similar to bool:
>> 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
> This will make DoneMeta a one-shot, meaning you'll have to make more
> DoneMeta's if you need more than one unsubclassable class.
For my purposes, that's enough -- I only have one object that I actually
need, something which is like None or Ellipsis or NotImplemented, just a
unique and featureless point-particle with no state or behaviour (apart
from a neat repr).
Yes yes, it's that damn singleton design (anti-)pattern again :-)
It's a bit ... something ... that to make a single stateless, behaviourless
instance I need a class and a metaclass, but that's Python for you.
As an alternative, I may use a single Enum, and delete the class object
after I've extracted the enumeration:
from enum import Enum
DONE = 'Done'
DONE = DoneType(DONE)
Although enumerations have more behaviour than I need, maybe this is close
enough that I don't care.
>> 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>'
> And this has to do with single instances, which is not what you asked
Very observant of you :-)
> Here's some sample code that creates a Final class; any class that
> subclasses from it cannot be further subclassed:
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.
More information about the Python-list