A class like Python that remembers arithmetic operations?

I am wondering if there is a python module that will allow me to do something like this:

x = MagicNumber() x.value = 3 y = 2 * (x + 2) ** 2 - 8 print y # 42 x.value = 2 print y # 24 

So MagicNumber will implement all the special operator methods, and they all return MagicNumber instances, keeping track of which operations are performed. Is there such a class?

EDIT: clarification

I want to use this in a module that needs to remember many parameters of some arbitrary calculations that the user wants to perform. Thus, the user will set the parameters and then use them to get his result. Then, if he decides that he would like to change the parameter, this change will immediately affect its result. Thus, a very simplified use session with a single instance of the parameter will look like this:

 p = MyParams() p.distance = 13.4 # I use __getattr__ and __setattr__ such that p.speed = 3.14 # __getattr__ returns MagicNumber instances time = p.distance / p.speed 

EDIT 2: clarification

Well, I will do what I had to do from the very beginning. I provided the context.

You are an engineer, and you must prepare a LaTeX document that details the work and features of a prototype gadget. This is a task that you will do repeatedly for different prototypes. You are writing a small python LaTeX interface. For each prototype, you create a python module that generates the required document. In it, you enter LaTeX code when calculating variables as necessary, so that the calculations are in context. After a while, you will notice two problems:

  • The number of variables and parameters makes the locals messy, and variable names are hard to remember. You must group them into categories to track them all.
  • Sometimes you need to repeat the same calculation that spreads over the last couple of chapters and a dozen lines with a change in one or more parameters. You should find a way to avoid code duplication.

From this problem, an original question arises.

+8
python
source share
5 answers

Something like that?

 import operator MAKE_BINARY = lambda opfn : lambda self,other : BinaryOp(self, asMagicNumber(other), opfn) MAKE_RBINARY = lambda opfn : lambda self,other : BinaryOp(asMagicNumber(other), self, opfn) class MagicNumber(object): __add__ = MAKE_BINARY(operator.add) __sub__ = MAKE_BINARY(operator.sub) __mul__ = MAKE_BINARY(operator.mul) __radd__ = MAKE_RBINARY(operator.add) __rsub__ = MAKE_RBINARY(operator.sub) __rmul__ = MAKE_RBINARY(operator.mul) # __div__ = MAKE_BINARY(operator.div) # __rdiv__ = MAKE_RBINARY(operator.div) __truediv__ = MAKE_BINARY(operator.truediv) __rtruediv__ = MAKE_RBINARY(operator.truediv) __floordiv__ = MAKE_BINARY(operator.floordiv) __rfloordiv__ = MAKE_RBINARY(operator.floordiv) def __neg__(self, other): return UnaryOp(self, lambda x : -x) @property def value(self): return self.eval() class Constant(MagicNumber): def __init__(self, value): self.value_ = value def eval(self): return self.value_ class Parameter(Constant): def __init__(self): super(Parameter, self).__init__(0.0) def setValue(self, v): self.value_ = v value = property(fset=setValue, fget=lambda self: self.value_) class BinaryOp(MagicNumber): def __init__(self, op1, op2, operation): self.op1 = op1 self.op2 = op2 self.opn = operation def eval(self): return self.opn(self.op1.eval(), self.op2.eval()) class UnaryOp(MagicNumber): def __init__(self, op1, operation): self.op1 = op1 self.operation = operation def eval(self): return self.opn(self.op1.eval()) asMagicNumber = lambda x : x if isinstance(x, MagicNumber) else Constant(x) 

And here it is in action:

 x = Parameter() # integer division y = 2*x*x + 3*x - x//2 # or floating division # y = 2*x*x + 3*x - x/2 x.value = 10 print(y.value) # prints 225 x.value = 20 print(y.value) # prints 850 # compute a series of xy values for the function print([(x.value, y.value) for x.value in range(5)]) # prints [(0, 0), (1, 5), (2, 13), (3, 26), (4, 42)] 
+11
source share

You can give sympy , a computer algebra system written in Python, a try.

eg.

 >>> from sympy import Symbol >>> x = Symbol('x') >>> y = 2 * (x + 2) ** 2 - 8 >>> y 2*(x + 2)**2 - 8 >>> y.subs(x,3) 42 >>> y.subs(x,2) 24 
+7
source share

Isn't that called function ? This may sound like a simple answer, but I mean it sincerely.

 def y(x): return 2 * (x + 2) ** 2 - 8 

Don't you think about it in the wrong direction?

To clarify the question:

 class MyParams(): distance = 0.0 speed = 0.0 def __call__(self): return self.distance / self.speed p = MyParams() p.distance = 13.4 # These are properties p.speed = 3.14 # where __get__ returns MagicNumber instances time = p() # 4.26 p.speed = 2.28 time = p() # 5.88 

I think I am more in favor of this type of solution, although I see an advantage in the sympy module. Preference, I think.

+5
source share
 >>> magic = lambda x: eval('2 * (x + 2) ** 2 - 8') >>> magic(2) 24 >>> magic(3) 42 >>> magic = lambda x: eval('x ** 4') >>> magic(2) 16 >>> magic(3) 81 
+1
source share

I think the difficulty lies in how to maintain the priority of the operators, and not to implement the class.

I suggest looking at another notation (e.g. Reverse Polish Notation ), which can help get rid of priority issues ...

+1
source share

All Articles