Home > database >  Using Python Classes to print a bracketed expression
Using Python Classes to print a bracketed expression

Time:01-09

The expression is given as such:

e = Plus(Plus(Const(3),Const(4)),Const(5))

if I print(e) it should give me:

print(e)
(3 4) 5

My code is this, my logic is that for parent class value of prec is 0 so that when the class is evaluating inner Plus it should introduce '( )' as shown in the if-statment. Kindly correct my code. I am beginner here.

class Expr:
  prec=0
  def __str__(self):
    if self.prec>prec:
      return "(" str(self.l) self.op str(self.r) ")"
    else:
      return str(self.l)   self.op   str(self.r)


class Plus(Expr) :
  op=' '
  prec=1
  def __init__(self,l,r) :
    self.l = l
    self.r = r

class Const(Expr) :
  def __init__(self,v) :
    self.v = v

  def __str__(self):
    return str(self.v)

e = Plus(Plus(Const(3),Const(4)),Const(5))

print(e)
#(3 4) 5

CodePudding user response:

It looks like prec should be a parameter passed to the __str__ function.

class Expr:
    def __init__(self):
        self.prec = 0
        self.nb_operands = 0
    def __str__(self, prec=0):
        if self.nb_operands == 0:
            return str(self.v)
        elif self.nb_operands == 1:
            return self.op   self.v.__str__(self.prec)
        elif self.nb_operands == 2:
            if self.prec < prec:
                return ''.join([
                    "(",
                    self.l.__str__(self.prec),
                    self.op,
                    self.r.__str__(self.prec),
                    ")"
                ])
            else:
                return self.op.join((
                    self.l.__str__(self.prec),
                    self.r.__str__(self.prec)
                ))

class Plus(Expr) :
    def __init__(self,l,r) :
        self.op = ' '
        self.prec = 1
        self.nb_operands = 2
        self.l = l
        self.r = r

class Times(Expr) :
    def __init__(self,l,r) :
        self.op = '*'
        self.prec = 2
        self.nb_operands = 2
        self.l = l
        self.r = r

class Minus(Expr) :
    def __init__(self,v) :
        self.op = '-'
        self.prec = 1
        self.nb_operands = 1
        self.v = v

class Const(Expr) :
    def __init__(self,v) :
        self.prec = 0
        self.v = v
        self.nb_operands = 0

Testing:

print( Plus(Plus(Const(3),Const(4)),Const(5)) )
3 4 5

print( Plus(Times(Const(3),Const(4)),Const(5)) )
3*4 5

print( Times(Plus(Const(3),Const(4)),Const(5)) )
(3 4)*5

print( Times(Plus(Const(3),Const(4)),Minus(Const(5))) )
(3 4)*-5

CodePudding user response:

This is a supplement to @Stef's terrific answer. I wanted to show a way to keep the class code simple while maintaining the elegance of her/his recursive process -

class Expr:
  def __init__(self):
    self.prec = 0
    self.nb_operands = 0
  def __str__(self):
    return to_str(self)   # keep classes simple

Where to_str is defined as an ordinary function. Avoiding over a dozen instances of self and manual calls to __str__ improves readability -

def to_str(e, prec=0):
  match e.nb_operands: 
    case 0:
      return str(e.v)
    case 1:
      return e.op   to_str(e.v, e.prec)
    case 2:
      if e.prec < prec:
        return ''.join([
          "(",
          to_str(e.l, e.prec),
          e.op,
          to_str(e.r, e.prec),
          ")"
        ])
      else:
        return e.op.join([
          to_str(e.l, e.prec),
          to_str(e.r, e.prec)
        ])
  •  Tags:  
  • Related