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
- 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
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.
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 return
ed, 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,
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,
the %
in the middle is the formatting operator itself
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