Making special method names, work with __getattr__
Chris Rebert
clp2 at rebertia.com
Fri Apr 23 12:32:55 EDT 2010
On Fri, Apr 23, 2010 at 2:41 AM, Antoon Pardon <apardon at forel.vub.ac.be> wrote:
> The following is a proof of concept. The idea is to have variables that
> represent symbolic names/expressions, you can work with like ordinary
> values, but that can be evaluated later.
>
> This is the code:
>
> ------------------------------------------------------------------------
>
> import operator
> from functools import partial
>
> class Expression (object) :
> def __add__(self, term):
> return Binary(self, operator.__add__, term)
>
> def __getattr__(self, name):
> op = getattr(operator, name)
> return partial(Binary, self, op)
>
> class Binary (Expression) :
> def __init__(self, left, op, right):
> self.left = left
> self.operator = op
> if not isinstance(right, Expression):
> right = Value(right)
> self.right = right
>
> def eval(self, dct):
> left = self.left.eval(dct)
> right = self.right.eval(dct)
> return self.operator(left, right)
>
>
> class Symbol (Expression):
> def __init__(self, name):
> self.name = name
>
> def eval(self, dct={}):
> return dct[self.name]
>
>
> class Value (Expression):
> def __init__(self, val):
> self.value = val
>
> def eval(self, dct={}):
> return self.value
>
> def test():
> dct = {"var1" : 5, "var2" : 7}
> val1 = Symbol("var1")
> val2 = Symbol("var2")
> print val1.eval(dct)
> sum = val1 + 3
> print sum.eval(dct)
> sum = sum + val2
> print sum.eval(dct)
> product = val1 * 7
> print product.eval(dct)
>
> test()
>
> --------------------------------------------------------------------------
>
> The result I get is:
>
> 5
> 8
> 15
> Traceback (most recent call last):
> File "Symbolics", line 54, in <module>
> test()
> File "Symbolics", line 51, in test
> product = val1 * 7
> TypeError: unsupported operand type(s) for *: 'Symbol' and 'int'
>
> What I had hoped for was, that the line:
>
> product = val1 * 7
>
> would be translated into something like
>
> product = val1.__mul__(7)
That's basically correct.
> which would then be treated by the __getattr__ of the Expression superclass.
>
> That doesn't seem to happen.
Indeed it doesn't. The lookup of fouble-underscore special methods
bypasses __getattribute__() and friends. For details, see
http://docs.python.org/reference/datamodel.html#special-method-lookup-for-new-style-classes
> Does anyone have another idea, so I can get this to work without having
> to manually add all numeric special methods to the Expression class.
You could write a decorator to make it a bit less painful/repetitive,
but no, you're gonna have to define all the methods individually.
Cheers,
Chris
--
http://blog.rebertia.com
More information about the Python-list
mailing list