Skip to content

Python 3.13.3 runs __iter__ twice in a list comprehension #132711

Description

@fb2078

Bug report

Bug description:

I can't upload comprehensionTestbed2.py because I am told the .py type is not allowed so I here is the script I used to reproduce this issue:

===========================================

# TestClass: Class that interacts with the DVD data file.

class TestClass:
    # Initialize the file timestamp.
    def __init__(self):
        pass
    # The iterator method.
    def __iter__(self):
        print('S1')
        self._index = 0
        return self
    # The next method.
    def __next__(self):
        print('S5')
        if self._index == 5:
            raise StopIteration
        value = self._index
        self._index += 1
        return value


# Test code.

print('#1')
for n in TestClass():
    print(n)

print('#2')
numbers = [n for n in TestClass()]
print(numbers)

==============================================

Here is the output of the Python script above:

D:\Files\Testing> comprehensionTestbed2.py                
#1                                                        
S1                                                        
S5                                                        
0                                                        
S5                                                        
1                                                        
S5                                                        
2                                                        
S5                                                        
3                                                        
S5                                                        
4                                                        
S5                                                        
#2                                                        
S1                                                        
S1  <-----  The __iter__ method is invoked twice in the list comprehension when using 3.13.3 (and 3.13.2).                                            
S5                                                        
S5                                                        
S5                                                        
S5                                                        
S5                                                        
S5                                                        
[0, 1, 2, 3, 4]                                           

This does not happen with python 3.12.9 and is a real problem when the iter method creates a mutex.

Edward

CPython versions tested on:

3.13

Operating systems tested on:

Windows

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Apr 18, 2025
  2. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    3.13only security fixes
    3.14bugs and security fixes
    on Apr 18, 2025
  3. picnixz commented on Apr 18, 2025

    @picnixz
  4. picnixz commented on Apr 18, 2025

    @picnixz
    Member

    Ah, could it be a duplicate of #127682?

  5. added
    pendingThe issue will be closed if no feedback is provided
    on Apr 18, 2025
  6. efimov-mikhail commented on Apr 19, 2025

    @efimov-mikhail
    Member

    Ah, could it be a duplicate of #127682?

    I think so, this is a duplicate.

  7. fb2078 commented on Jun 19, 2025

    @fb2078
    Author
  8. efimov-mikhail commented on Jun 19, 2025

    @efimov-mikhail
    Member

    Unfortunately, we can't fix this bug without producing other bigger problems. So, fix in 3.13.4 was reverted.

    You can read this topic for more information: https://discuss.python.org/t/python-3-13-5-is-now-available-yes-really/95211

  9. fb2078 commented on Jun 19, 2025

    @fb2078
    Author
  10. efimov-mikhail commented on Jun 20, 2025

    @efimov-mikhail
    Member

    For my benefit, is the __iter__ method always called twice or only sometimes when in a comprehension?

    Only in comprehensions.

    JFR, the most correct way for writing related code is to always define __iter__ method for iterator objects this way:

    def __iter__(self):
        return self
  11. fb2078 commented on Jun 21, 2025

    @fb2078
    Author
  12. fb2078 commented on Jun 21, 2025

    @fb2078
    Author
  13. efimov-mikhail commented on Jun 21, 2025

    @efimov-mikhail
    Member

    That works but it seems that the iter method is not really supposed do anything but just return self.

    Yes, __iter__ method should be idempotent without side effects, so calling it twice gives the same result as calling it one time.

    Is it possible that the issue of __iter__ being called more than once will be fixed in 3.14 or later version?

    It's already fixed on 3.14 branch, you can test on fresh beta: https://discuss.python.org/t/python-3-14-0-beta-3-is-here/95843

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13only security fixes3.14bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)pendingThe issue will be closed if no feedback is providedtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions