How to prevent the use of a class as a base class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class terminal(type):
def __init__(self, cl_name, bases, namespace):
for cls in bases:
if isinstance(cls, terminal):
raise TypeError("in "+cl_name+" definition : "+str(cls)+
" can't be used as a base class")
super(terminal, self).__init__(cl_name, bases, namespace)
# first we create a normal class
class a(object):
pass
#the terminal class: it can inherit from other classes but can't be
#used as base class
class b(a):
__metaclass__= terminal
#this will fail at compile time, because inheriting from b is forbidden
class c(b):
pass
|
Some constructs, like the one I used in the ring buffer recipe http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68429 don't play nicely with inheritance. In such case, it can be useful to have a safeguard.
This is done here by the terminal metaclass, which check if one of the base classes type is the terminal metaclass. Since inheritance also transmit metaclass, the check will be done on the terminal instance subclasses.
does not work if super class already has a metaclass. If class a already has a metaclass then a "metatype conflict among bases" is raised.
For example, I might define a tracer class as metaclass for class a to be traced.
So question is how can class b be defined to have two metaclasses i.e. get tracing facility from class a and also be defined as a final class.
Forbidding inheritance. Have a look at my recipe
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/204197
which solves the metaclass conflict.