Emulating Final classes in Python
Ethan Furman
ethan at stoneleaf.us
Tue Jan 17 14:14:13 EST 2017
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 subclassed')
This will make DoneMeta a one-shot, meaning you'll have to make more DoneMeta's if you need more than one unsubclassable class.
> 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 about.
Here's some sample code that creates a Final class; any class that subclasses from it cannot be further subclassed:
-- 8< ------------------------------------------------------------
Final = None
class FinalMeta(type):
def __new__(metacls, cls, bases, clsdict):
print('-' * 50)
print('class: ', cls)
print('bases: ', bases)
if Final is not None:
for base in bases:
if base is not Final and issubclass(base, Final):
print('should raise')
print('-' * 50)
return type.__new__(metacls, cls, bases, clsdict)
class Final(metaclass=FinalMeta):
pass
class One(Final):
pass
class Two(One):
pass
class Three(Two):
pass
class Ten(Final):
pass
-- 8< ------------------------------------------------------------
Change the "should raise" to a raise, remove the other print()s, and away you go.
Should work in any Python 3.
--
~Ethan~
More information about the Python-list
mailing list