Python Forum

Full Version: Magic method __str__
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi all, I´m trying to make a method __str__ for my class. It should have just one line (return ...) as usually this method is supposed to look like, and it should create a string from two dimensional list. List contains 9 lines, each with 9 items (items can be "." or number 1-9) separated by a space. What do I have so far is this:

    def __str__(self):
        my_str = ""
        for line in self.tab:
            for item in range(len(line)):
                my_str += str(line[item]) + " "
            my_str += "\n"
        return my_str
As you can see, this takes many lines, but it should be just in one. Can you help me with that? Thanks.
def __str__(self):
    return "\n".join([" ".join(x) for x in self.tab])
dan789 Wrote:it should have just one line (return ...) as usually this method is supposed to look like
There is no special rule concerning the __str__() method. It is supposed to return a str instance but it can be 20000 lines long if you want (yes I tested this).
@stullis seems like it could work, but there is a problem with integers in a list. Numbers 1-9 are integers, not strings, what means that this generator notation doesn´t work there.

@Gribouillis I thought so, but if there is a way how to make this method 1 line, I prefer it.
(Dec-18-2018, 07:17 PM)dan789 Wrote: [ -> ]if there is a way how to make this method 1 line, I prefer it.
can you give an example as it's not very clear (i.e. input and desired output) e.g. list contains lines?
This is the content of two dimensional list:

[['.', '.', '.', '.', '.', 9, '.', '.', '.'], ['.', '.', 7, '.', 8, 6, '.', '.', '.'], [6, '.', '.', 3, '.', '.', '.', '.', '.'], ['.', 4, '.', '.', '.', 7, '.', '.', 8], ['.', '.', '.', '.', '.', '.', '.', 3, 2], ['.', '.', 3, 6, '.', 5, 1, '.', '.'], ['.', 6, '.', 7, '.', '.', '.', 8, '.'], [3, '.', 2, '.', '.', '.', 4, 9, '.'], ['.', 5, 4, 8, '.', '.', '.', '.', 3]]
What do I want to get is:

. . . . . 9 . . .
. . 7 . 8 6 . . .
6 . . 3 . . . . .
. 4 . . . 7 . . 8
. . . . . . . 3 2
. . 3 6 . 5 1 . .
. 6 . 7 . . . 8 .
3 . 2 . . . 4 9 .
. 5 4 8 . . . . 3
what @stullis suggested with small amendment
def __str__(self):
    return "\n".join([" ".join(map(str, sub_list)) for sub_list in self.tab])
Well, this works, thanks. :)

But now I need to create a copy of this list, since I need to call this method later again, after some other methods change self.tab, but I want __str__() to return still the same list. I tried to make a copy of self.tab using "self.tab.copy()" into new variable and this used in __str__(). But whenever I call __str__() after something changed in self.tab, it also changes in self.tab_copy. How to deal with that?

I simply added into __init__ new variable self.tab_copy and in __str__() changed to "return "\n".join([" ".join(map(str, x)) for x in self.tab_copy])", but is still changes the inital self.tab (as I described above).
I have a longer solution, but as your data resembles a Sudoku board, I think it might be interesting
allbox = u''.join(chr(9472 + x) for x in range(200))
box = [ allbox[i] for i in (2, 0, 12, 16, 20, 24, 44, 52, 28, 36, 60) ]
(vbar, hbar, ul, ur, ll, lr, nt, st, wt, et, plus) = box
hh = hbar * 7
nl = '\n'

topline = ul + (hh + nt) * 2 + hh + ur
midline = wt + (hh + plus) * 2 + hh + et
botline = ll + (hh + st) * 2 + hh + lr

def to_str(board):
    result = [topline + nl]
    for i, z in zip(range(0, 9, 3), (midline + nl, midline + nl, botline)):
        for row in board[i:i+3]:
            result.append(
                vbar + vbar.join(
                    ' ' + ' '.join(str(k) for k in row[j:j+3]) + ' ' for j in range(0, 9, 3)) + vbar + nl) 
        result.append(z)
    return ''.join(result)

if __name__ == '__main__':
    data = [
        ['.', '.', '.', '.', '.', 9, '.', '.', '.'],
        ['.', '.', 7, '.', 8, 6, '.', '.', '.'],
        [6, '.', '.', 3, '.', '.', '.', '.', '.'],
        ['.', 4, '.', '.', '.', 7, '.', '.', 8],
        ['.', '.', '.', '.', '.', '.', '.', 3, 2],
        ['.', '.', 3, 6, '.', 5, 1, '.', '.'],
        ['.', 6, '.', 7, '.', '.', '.', 8, '.'],
        [3, '.', 2, '.', '.', '.', 4, 9, '.'],
        ['.', 5, 4, 8, '.', '.', '.', '.', 3]]
    print(to_str(data))
Output:
┌───────┬───────┬───────┐ │ . . . │ . . 9 │ . . . │ │ . . 7 │ . 8 6 │ . . . │ │ 6 . . │ 3 . . │ . . . │ ├───────┼───────┼───────┤ │ . 4 . │ . . 7 │ . . 8 │ │ . . . │ . . . │ . 3 2 │ │ . . 3 │ 6 . 5 │ 1 . . │ ├───────┼───────┼───────┤ │ . 6 . │ 7 . . │ . 8 . │ │ 3 . 2 │ . . . │ 4 9 . │ │ . 5 4 │ 8 . . │ . . 3 │ └───────┴───────┴───────┘
(Dec-18-2018, 08:37 PM)dan789 Wrote: [ -> ]But now I need to create a copy of this list, since I need to call this method later again
You should be able to call str(the_object) an infinite number of times, and not have any data change. If you're copying lists inside the __str__ function, you're doing something horribly wrong. Please, share some code, instead of giving tiny little glimpses of what might be lurking under the surface of your code.
Pages: 1 2