Trapping numeric operators

J

John Dell'Aquila

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__'),
}
 
J

John Dell'Aquila

The lambda wrapper does impose the overhead of an extra function call:
classdict[magicName] = (
lambda self, other=None, name=magicName, op=op, fn=fn:
fn(self, other, name, op)
)

I could eliminate that by stubbing out the closure and inserting the
code block directly into it:
stub = lambda self, other=None, name=magicName, op=op: self
stub.func_code = fn.func_code
classdict[magicName] = stub

What do folks think -- useful trick or too squirrelly to countenance?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,588
Members
45,093
Latest member
Vinaykumarnevatia00

Latest Threads

Top