Chengming Gu
Chengming Gu

Reputation: 67

Linked List Class __str__ function

I want to create this function

    >>> str(Link('Hello'))
    'Hello'

    >>> str(Link(1, Link(2)))
    '1 -> 2'

    >>> print(Link(1 / 2, Link(1 // 2)))
    0.5 -> 0

    >>> str(Link(Link(1, Link(2, Link(3))), Link(4, Link(5))))
    '(1 -> 2 -> 3) -> 4 -> 5'

    >>> print(Link(Link(Link(Link('Wow')))))
    (((Wow)))

    >>> print(Link(Link('a'), Link(Link('b'), Link(Link('c')))))
    (a) -> (b) -> (c)

Here is my code:

def __str__(self):
    result = ''
    while self.rest is not Link.empty:
        result += '{0} -> '.format(self.first)
        self = self.rest
    return result + '{0}'.format(self.first)

However, I do not know what to do in order to fulfill the last three doctests. Help!!!

class Link(object):
   empty = ()
   def __init__(self, first, rest=empty):
       self.first = first
       self.rest = rest

Upvotes: 1

Views: 509

Answers (1)

abarnert
abarnert

Reputation: 365925

It looks like the rule is supposed to be that if the head of a list is itself a list, you format that list, and put it in parentheses. Something like this:

first = '({0})'.format(self.first) if isinstance(self.first, Link) else first
result += '{0} -> '.format(first)

Now, it's a bit strange to avoid using recursion on rest, but then indirectly use recursion on first. (That's what '{0}'.format(…) does—if you haven't defined a __format__ method, it calls your __str__ method.)

So, assuming this is an assignment, if the assignment tells you to not use recursion, you're going to need to turn that into a loop. If, on the other hand, the assignment doesn't say to avoid recursion, it would be a lot simpler to just recurse on both:

first = str(self.first)
if isinstance(self.first, Link):
    first = '({0})'.format(first)
if self.rest is Link.empty:
    return first
return '{0} -> {1}'.format(first, self.rest)

As a side note: This is a stock Scheme exercise ported badly to Python (which implies that your teacher either doesn't get or doesn't like Python, which isn't a great sign…), but it's missing a piece.

Normally, you're supposed to handle, e.g., Link(1, 2) differently from Link(1, Link(2)). (In Lisp terms, that's (1 . 2) vs. (1 2).) But none of the examples you gave test for that, so it's not clear exactly what you're supposed to output for the former. Sp… be prepared to be marked off for not reading your teacher's mind, unless you want to do something like this:

first = str(self.first)
if isinstance(self.first, Link):
    first = '({0})'.format(first)
if self.rest is Link.empty:
    return first
rest = str(self.rest)
if isinstance(self.rest, Link):
    return '{0} -> {1}'.format(first, self.rest)
else:
    # surely (1 2 . 3) is not the same list as (1 2 3) but the spec left it out?
    return '{0} .. {1}'.format(first, self.rest)

Upvotes: 3

Related Questions