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

AltStyle によって変換されたページ (->オリジナル) /