[issue41407] Tricky behavior of builtin-function map

DarrenDanielDay report at bugs.python.org
Mon Jul 27 06:01:38 EDT 2020


New submission from DarrenDanielDay <Darren_Daniel_Day at hotmail.com>:

# The following is a tricky example:

# This is an example function that possibly raises `StopIteration`.
# In some cases, this function may raise `StopIteration` in the first iteration.
def raise_stop_iteration(param):
    if param == 10:
        raise StopIteration
    # Suppose this function will do some simple calculation
    return -param

# Then when we use builtin-function `map` and for-loop:

print('example 1'.center(30, '='))
for item in map(raise_stop_iteration, range(5)):
    print(item)
print('end of example 1'.center(30, '='))

# It works well. The output of example 1 is 0 to -4.
# But the following can be triky:

print('example 2'.center(30, '='))
for item in map(raise_stop_iteration, range(10, 20)):
    print(item)
print('end of example 2'.center(30, '='))

# The output of exapmle 2 is just nothing,
# and no errors are reported,
# because `map` simply let the exception spread upward when executing `raise_stop_iteration(10)`.
# However, the exception type is StopIteration, so the for-loop catches it and breaks the loop,
# assuming this is the end of the loop.
# When the exception raised from buggy mapping function is exactly `StopIteration`, 
# for example, functions implemented with builtin-function `next`, 
# it can be confusing to find the real issue.

# I think it might be better improved in this way:

class my_map:
    def __init__(self, mapping_function, *iterators):
        self.mapping = mapping_function
        self.iterators = iterators
    
    def __iter__(self):
        for parameter_tuple in zip(*self.iterators):
            try:
                yield self.mapping(*parameter_tuple)
            except BaseException as e:
                raise RuntimeError(*e.args) from e
        
# It works like the map in most cases:

print('example 3'.center(30, '='))
for item in my_map(raise_stop_iteration, range(5)):
    print(item)
print('end of example 3'.center(30, '='))

# And then, the crash of the buggy mapping function will be reported:
print('example 4'.center(30, '='))
for item in my_map(raise_stop_iteration, range(10, 20)):
    print(item)
print('end of example 4'.center(30, '='))

----------
components: Library (Lib)
files: issue.py
messages: 374371
nosy: DarrenDanielDay
priority: normal
severity: normal
status: open
title: Tricky behavior of builtin-function map
type: behavior
versions: Python 3.7
Added file: https://bugs.python.org/file49342/issue.py

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41407>
_______________________________________


More information about the Python-bugs-list mailing list