Emulating Final classes in Python

Ethan Furman ethan at stoneleaf.us
Wed Jan 18 11:24:26 EST 2017


On 01/17/2017 11:05 PM, Steven D'Aprano wrote:

> I've given a metaclass that disallows subclassing:
>
> class MyClass(MyParent, metaclass=FinalMeta):
>      ...
>
>
> Ethan took that one step further by giving a class you inherit from to disallow
> subclassing:
>
> class MyClass(MyParent, Final):
>      ...
>
>
> Could we solve this problem with a decorator?
>
>
> @final
> class MyClass(MyParent):
>      ...
>
>
> Without needing to add any special magic to MyParent or MyClass, apart from the
> decorator, can we make MyClass final? That would (in principle) allow us to
> make a subclass, and *then* set the class final so that no more subclasses
> could be made.
>
>
> I thought that the decorator could simply set the class' metaclass:
>
> def final(cls):
>      if cls.__class__ is type:
>          cls.__class__ = Meta
>          return cls
>      raise TypeErrror('Possible metaclass conflict')
>
>
> but that's disallowed. Any ideas?

You still need to have the FinalMeta type and Final class available, but to use a decorator you'll need to scavenge the bits from the old class to make a new class of the same name and return that:

def final(cls):
     new_cls = Meta(cls.__name__, (Final, )+cls.__bases__, dict(cls.__dict__))
     return new_cls

Not sure if more is needed to handle __slots__, but this should get us started.

--
~Ethan~


More information about the Python-list mailing list