== Exploiting Python metaclasses to forbid subclassing and where it fails Suppose, entirely hypothetically and purely for illustration, that you want to create a class that cannot be subclassed. Python is normally a very permissive language, but as I mentioned in passing [[yesterday MetaclassCallableIssues]] you can abuse some metaclass features to do this. Well, to more or less do this; as it happens there is a way around it because Python allows callables to be specified as your metaclass. While there are complex approaches with a single metaclass that has a sophisticated ((__new__)), it's easier to illustrate the whole idea like this (in Python 3 for once): .pn prewrap on > class Block(type): > def __new__(meta, cname, bases, cdict): > raise TypeError("cannot subclass") > > def metacls(cname, bases, cdict): > return type.__new__(Block, cname, bases, cdict) > > class A(metaclass=metacls): > pass This works basically by cheating; our callable metaclass gives the newly created class a different metaclass that blocks the creation of further classes in its ((__new__)). So let's try to get tricky to get around this. Our first attempt is to give our new subclass a different metaclass that doesn't block class creation: > class MNothing(type): > pass > > class B(A, metaclass=MNothing): > pass This will fail: > TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases But wait, we don't actually need a new class here. We just need something that allows class creation but gives the new class the metaclass it needs in order to not have a metaclass conflict. As it happens we already have that: > class B(A, metaclass=metacls): > pass (note that if we didn't have _metacls()_, creating it is trivial. _type(A)_ will give us the metaclass class we need to shim in.) This not only works, this is the simple and more or less ultimate bypass for anything that tries to block ((__new__)) because ~~using a callable as the metaclass splits apart what happens to a class as it's being created from the class's metaclass class~~. The new class's official post-creation metaclass gets no chance to intervene during creation; it just winds up being the metaclass of a new class by fiat, with nothing to say about it. Since the metaclass's ((__init__)) (if any) doesn't get called here, the first our _Block_ metaclass can possibly know about the new class is when the new class is used for something (attribute lookup, instance creation, or subclassing). All of which goes to show that Python is permissive after all if you know the right tricks, even if it looks restrictive initially. (Well, at least here.)