Introduction
This page describes a python mathematical expression tree
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# https://www.teach.cs.toronto.edu/~csc148h/notes/trees/expression_trees.html
#from __future__ import annotations
from typing import Any
class Expr:
"""An abstract class representing a Python expression.
"""
def evaluate(self) -> Any:
"""Return the *value* of this expression.
The returned value should be the result of how this expression would be
evaluated by the Python interpreter.
"""
raise NotImplementedError
class Num(Expr):
"""An numeric constant literal.
Attributes:
n: the value of the constant
"""
n: int | float
def __init__(self, number: int | float) -> None:
"""Initialize a new numeric constant."""
self.n = number
def evaluate(self) -> Any:
"""Return the *value* of this expression.
The returned value should be the result of how this expression would be
evaluated by the Python interpreter.
>>> number = Num(10.5)
>>> number.evaluate()
10.5
"""
return self.n # Simply return the value itself!
class BinOp(Expr):
"""An arithmetic binary operation.
Attributes:
left: the left operand
op: the name of the operator
right: the right operand
Representation Invariants:
- self.op == '+' or self.op == '*'
"""
left: Expr
op: str
right: Expr
def __init__(self, left: Expr, op: str, right: Expr) -> None:
"""Initialize a new binary operation expression.
Precondition: <op> is the string '+' or '*'.
"""
self.left = left
self.op = op
self.right = right
def evaluate(self) -> Any:
"""Return the *value* of this expression.
"""
left_val = self.left.evaluate()
right_val = self.right.evaluate()
if self.op == '+':
return left_val + right_val
elif self.op == '*':
return left_val * right_val
else:
raise ValueError(f'Invalid operator {self.op}')
# added extra to test operator
def __add__(self, other):
if isinstance(other, Expr):
return BinOp(self,'+',other)
elif isinstance(other, int | float):
return BinOp(self,'+',Num(other))
else:
raise NotImplementedError
@classmethod
def number(cls, num):
"Initialize number"
return cls(Num(0.0),'+',Num(num))
# test number as expression and add operator
x = BinOp.number(10)
y = (x + 10).evaluate()
a = BinOp(Num(3), '+', Num(5.5))
# ((3 + 5.5) * (0.5 + (15.2 * -13.3)))
b = BinOp(
BinOp(Num(3), '+', Num(5.5)),
'*',
BinOp(
Num(0.5),
'+',
BinOp(Num(15.2), '*', Num(-13.3))))
print(a.evaluate())
print(b.evaluate())
#20.0
#8.5
#-1714.11