Pretty printing polynomials with dictionary python

2019-08-06 13:43发布

问题:

I'm struggling to create the __ str __ function (aka pretty print) with polynomials, where dictionaries are used to contain the powers as keys and the elements as coefficients. I have done it with lists but I haven't mastered dictionaries yet. Is there anything to improve?

You can see in the second polynomial that if my last constant is not a constant, after arranging the keys with the reverse() function, the plus is always there, what can i do to prevent that? By the way I am trying to overload operators, after I've done this I'll try to do __ add__, __ mul__, __ sub__, and __ call__... though I would finish this one first :P

class Polynomial(object):                                
  def __init__(self, coefficients):
    self.coefficients = coefficients

  def __str__(self):
     polyd = self.coefficients
     exponent = polyd.keys()  
     exponent.reverse()          
     polytostring = ' '
     for i in exponent:
        exponent = i
        coefficient = polyd[i]
        if i == 0:
            polytostring += '%s' % coefficient
            break
        polytostring += '%sx^%s + ' % (coefficient, exponent)


     return polytostring


dict1 = {0:1,1:-1}
p1 = Polynomial(dict1)

dict2 = {1:1,4:-6,5:-1, 3:2}
p2 = Polynomial(dict2)

print p1
print p2

回答1:

  1. Remove break statement because for loop will end(break) when exponent value is equal to 0.

code:

class Polynomial(object):                                
    def __init__(self, coefficients):
        self.coefficients = coefficients

    def __str__(self):
        polytostring = ' '
        for exponent, coefficient in self.coefficients.iteritems():
            if exponent == 0:
                polytostring += '%s + ' % coefficient
            else:
                polytostring += '%sx^%s + ' % (coefficient, exponent)

        polytostring = polytostring.strip(" + ")

        return polytostring


dict1 = {0:1, 1:-1}
p1 = Polynomial(dict1)

dict2 = {1:1, 4:-6, 5:-1, 3:2}
p2 = Polynomial(dict2)

print "First:-", p1
print "Second:-", p2

Output:

$ python poly.py 
First:- 1 + -1x^1
Second:- 1x^1 + 2x^3 + -6x^4 + -1x^5


回答2:

Something like this seems to work, if I understand your problem:

def format_term(coef, exp):
    if exp == 0:
        return "%d" % coef
    else:
        return "%dx^%d" % (coef, exp)

def format_poly(d):
    items = sorted(d.items(), reverse=True)
    terms = [format_term(v,k) for (k,v) in items]
    return " + ".join(terms)

dict1 = {0:1,1:-1}
print(format_poly(dict1))    # -1x^1 + 1

dict2 = {1:1,4:-6,5:-1, 3:2}
print(format_poly(dict2))    # -1x^5 + -6x^4 + 2x^3 + 1x^1

It just sorted the (key,val) pairs by key, then formats each term, and joins the terms into a single string.



回答3:

This is compact

def __str__(self):return"".join("%+gx^%d"%(self.coefficients[e],e)for e in sorted(self.coefficients.keys(),reverse=1))

and works...


Let's have a look at the expression that is returned, a piece at a time

"".join(...)

One of the string methods is .join() that accepts a sequence of strings and joins them with the (in this case) null string, e.g.

" + ".join(["a", "b", "c"] => "a + b + c"

In our case the argument of join is

"%+gx^%d"%(self.coefficients[e],e)for e in sorted(self.coefficients.keys(),reverse=1)

that, parenthesized, is a generator expression, that, btw, is similar to an implicit for loop.

On the right there is

for e in sorted(self.coefficients.keys(),reverse=1))

that assign to the local variable e, in turn, the keys of self.coefficients in sorted and reversed order

and on the left there is the result of the generator expression, evaluated for each possible value of e

"%+gx^%d"%(self.coefficients[e],e)

The expression above is known as string formatting or interpolation and works like this,

  1. the string on the left is a format string and the parts in it prefixed by % are _format specifiers, here %+g means generic formatting always prefixed by the sign and %d means integer digit, whats outside (here `x^``) is copied vebatim into the result,

  2. the % in the middle is the formatting operator itself

  3. the tuple (self.coefficients[e], e) is the argument of the format string, you mnust have a 1 to 1 correspondance between format specifiers and arguments

At this point we have all the pieces in place... in a more colloquial form it could be

def __str__(self):
    # generated a correctly sorted list of exponents
    exps = sorted(self.coefficients.keys(),reverse=True)
    # generate a corretctly sorted list of coefficients
    coefs = [self.coefficients[e] for e in exps]
    # generate a list of formatted strings, one for each term
    reps = [ "%+gx^%d" % (c, e) for c, e in zip(coefs, exps)]
    # join the formatted strings
    poly_rep = "".join(reps)
    # let's end this story
    return poly_rep