Home Mathematical Expression Tree in Python
Post
Cancel

Mathematical Expression Tree in Python

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
This post is licensed under CC BY 4.0 by the author.

Linked List example in Python

-