3 ms·
This "infectious behaviour" (though perhaps unfairly characterised) leads to the clearest purpose of metaclasses. Metaclasses (and build_class) is a mechanism
by jamesdutc 13y ago
This "infectious behaviour" (though perhaps unfairly characterised) leads to the clearest purpose of metaclasses.
Metaclasses (and build_class) is a mechanism by which to enforce a constraint from a base type to a derived type.
(Note that, in practice, there is some trickiness around metaclasses on derived classes: http://seriously.dontusethiscode.com/2013/04/18/derived-metaclasses.html http://seriously.dontusethiscode.com/2013/04/18/derived-meta...)
It's trivial to enforce a constraint from a derived type to a base type. e.g.,
# base.py
class Base:
def spam(self): pass
# derived.py
class Derived(Base):
assert hasattr(Base, 'spam') # or abc, &c.
def ham(self):
return self.spam
But how can we enforce a constraint in the other direction? (e.g., abc.ABCMeta)
# base.py
from functools import wraps
class metaclass(type):
def __new__(m, n, b, d):
assert 'spam' in d # must implement, not just inherit
# can even enforce behaviour via wrapping
spam = d['spam']
@wraps(spam)
def wrap(*args, **kwargs):
print('wrap({}, {})'.format(args, kwargs))
return spam(*args, **kwargs)
d['spam'] = wrap
return type.__new__(m, n, b, d)
class Base(metaclass=metaclass):
def spam(self): pass
# derived.py
class Derived(Base):
def spam(self): pass