Ian Bicking’s comment suggesting I wasn’t far away from getting the MutableNumber class to work was quite correct. I had never considered using a descriptor, which made it difficult to make this work with a metaclass. The following code, though, does work:
class Operator(object):
def __init__(self, instance, op):
self.instance = instance
self.op = op
def __call__(self, rhs):
try:
return self.op(self.instance.number, rhs.number)
except AttributeError:
return self.op(self.instance.number, rhs)
class OperatorDescriptor(object):
def __init__(self, op):
self.op = op
def __get__(self, obj, type=None):
return Operator(obj, self.op)
def __set__(self, obj, value):
raise TypeError
def __delete__(self, obj):
raise TypeError
class NumberDelegateMetaclass(type):
def __init__(cls, name, bases, dct):
for attr in cls.__operatormap__:
setattr(cls, attr, OperatorDescriptor(getattr(operator, attr)))
class MutableNumber(object):
number = None
__metaclass__ = NumberDelegateMetaclass
__operatormap__ = "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", \
"__gt__", "__inv__", "__invert__", "__le__", "__lshift__", "__lt__", \
"__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", \
"__rshift__", "__sub__", "__truediv__"
def __init__(self, value=None):
self.number = value
It’s a miracle.