Python Forum
Why there is not __break__ dunder method
Poll: Did you think a __break__ dunder could be usefull
You do not have permission to vote in this poll.
Yes
50.00%
1 50.00%
No
50.00%
1 50.00%
Total 2 vote(s) 100%
* You voted for this item. [Show Results]

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Why there is not __break__ dunder method
#1
Hello,
Yesterday I ran into an issue, i try to iterate multiple time trough a custom class,
the class is a chess Board and iterating trough it would give a tuple of (x, y, tile) for each step of the loop

to iterate multiple time I store all the variable that I will need in the __next__ method into a list and add that list to another list, iter_list
but to work the __next__ method of the class delete the last element of iter_list juste before raising StopIteration
that mean that if someone use break while iterating this class, the last element of iter_list would not be deleted

So that why I ask this question, I search online and i saw that a can use the context manager but that didn't look good for me
and I think that it isn't an obvious way to do it

I think that a __break__ method would be usefull to iterate multiple time into a custom class and still use break inside the loop:
like this:
for *var0 in custom_iterator:
----for *var1 in custom_iterator:
--------# do something
--------if some_condition:
------------break

So I wonder why there is not __break__ method
Reply
#2
(May-13-2023, 02:43 PM)Phidias618 Wrote: So I wonder why there is not __break__ method
I think ther is no __break__ method because nobody needs it, so can you give a concrete example of what you want to do, because it is difficult to understand with an abstract description?
buran likes this post
Reply
#3
class SomeBoard:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.grid = [[0 for _ in range(width)] for _ in range(height)]
        self._iter_data: list[list] = []
    
    def __getitem__(self, co: tuple[int, int]):
        return self.grid[co[1]][co[0]]

    def __iter__(self):
        self._iter_data.append([-1, 0])
        return self

    def __next__(self):
        last = _iter_data[-1]
        last[0] += 1
        if last[0] == self.width:
            last[0] = 0
           last[1] += 1
            if last[1] == self.height:
                del self._iter_data[-1]
                raise StopIteration

        return last[0], last[1], self.grid[last[0], last[1]]

board = SomeBoard(8, 8)
# do something with it

for x, y, tile in board:
    break

print(board._iter_data)
The probleme is that i can't break when I iterate trough CustomBoard, because that will leave date inside _iter_data
with a __break__ dunder I could simply solve this by:
def __break__(self):
    del self._iter_data[-1]
And now the iterator will work properly

But if _iter_data were only made of one list containing the x and y coordinate then I couldn't iterate trough a CustomBoard instance like this:
board = CustomBoard(8, 8)
for x1, y1, tile1 in board:
    for x2, y2, tile2 in board:
        # do something 
        ...
The problem now is that this program will result in an endless loop
Reply
#4
I don't understand exactly what your code is doing but in complex cases, a good design is to create an iterator class separate from the class upon which you iterate. This iterator class will carry the data necessary to the iteration steps and also the specific code, so the structure could be
class SomeBoard:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.grid = [[0 for _ in range(width)] for _ in range(height)]

    def __getitem__(self, co: tuple[int, int]):
        return self.grid[co[1]][co[0]]

    def __iter__(self):
        return BoardIterator(self)


class BoardIterator:
    def __init__(self, board):
        self.board = board
        self._iter_data = [[-1, 0]]

    def __iter__(self):
        return self

    def __next__(self):
        ... # custom iteration code here



board = SomeBoard(8, 8)
# do something with it

for x, y, tile in board:
    break

print(board._iter_data)
Note that the SomeBoard class has no __next__ method here. A SomeBoard instance is iterable but it is not an iterator.
Reply
#5
Thanks you
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020