Making special method names, work with __getattr__

Antoon Pardon apardon at
Fri Apr 23 05:41:32 EDT 2010

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): = name

  def eval(self, dct={}):
    return dct[]

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)



The result I get is:

Traceback (most recent call last):
  File "Symbolics", line 54, in <module>
  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)

which would then be treated by the __getattr__ of the Expression superclass.

That doesn't seem to happen.

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.

Antoon Pardon

More information about the Python-list mailing list