Trapping numeric operators
John Dell'Aquila
dellaq at ml1.net
Thu Oct 21 22:52:06 EDT 2004
I want to trap numeric operators (+ * % etc.) so that my new style
classes can handle them generically, similar to __getattr__ in an old
style class.
I've never done any metaprogramming before but I'm thinking of using
the below metaclass to accomplish this. It reads a class variable,
implements_operators, to determine which methods handle various
operators, then inserts closures to call the generic methods with
disambiguating parameters (the name of the magic method and the
corresponding operator built-in, if it can be determined).
Is this a reasonable approach or an abuse of metaclasses? Any comments
would be deeply appreciated.
Thanks,
John
import operator # the metaclass
class metaOperator(type):
def __new__(cls, classname, bases, classdict):
fnDict = classdict['implements_operators']
for fn in fnDict.iterkeys():
for magicName in fnDict[fn]:
for opName in (magicName, '__%s'%magicName[3:]):
# try magicName else assume in-place/right
# and strip out the presumptive 'i'/'r'
try:
op = getattr(operator, opName)
break
except AttributeError:
pass
else:
op = None
classdict[magicName] = (
lambda self, other=None, name=magicName, op=op, fn=fn:
fn(self, other, name, op)
)
return type.__new__(cls, classname, bases, classdict)
class Q(object): # a sketch of its use
__metaclass__ = metaOperator
def binop(self, other, name, op): pass
def ibinop(self, other, name, op): pass
def unop(self, other, name, op): pass
implements_operators = {
binop: ('__add__','__sub__','__mul__','__div__'),
ibinop: ('__iadd__','__isub__','__imul__','__idiv__'),
unop: ('__neg__','__pos__','__abs__','__invert__'),
}
More information about the Python-list
mailing list