Repository: numpy/numpy
File: numpy/_core/strings.py (Python)

Code before:

    >>> np.strings.slice(a, np.array([1, 2]), np.array([4, 5]))
    array(['ell', 'rld'], dtype='<U5')

    Negative slices have the same meaning as in regular Python:

    >>> b = np.array(['hello world', 'γεια σου κόσμε', '你好世界', '👋 🌍'],
    ...              dtype=np.dtypes.StringDType())
    >>> np.strings.slice(b, -2)
    array(['hello wor', 'γεια σου κόσ', '你好', '👋'], dtype=StringDType())

    >>> np.strings.slice(b, -2, None)
    array(['ld', 'με', '世界', ' 🌍'], dtype=StringDType())

    >>> np.strings.slice(b, [3, -10, 2, -3], [-1, -2, -1, 3])
    array(['lo worl', ' σου κόσ', '世', '👋 🌍'], dtype=StringDType())

    >>> np.strings.slice(b, None, None, -1)
    array(['dlrow olleh', 'εμσόκ υοσ αιεγ', '界世好你', '🌍 👋'],
          dtype=StringDType())

    """
    # Just like in the construction of a regular slice object, if only start
    # is specified then start will become stop.
    # However if stop is specified as None, preserve its value.
    # See logic in slice_new.
    if stop is NULL:
        stop = start
        start = None

    # adjust start, stop, step to be integers, see logic in PySlice_Unpack
    if step is None:
        step = 1
    step = np.asanyarray(step)
    if not np.issubdtype(step.dtype, np.integer):
        raise TypeError(f"unsupported type {step.dtype} for operand 'step'")
    if np.any(step == 0):
        raise ValueError("slice step cannot be zero")

    if start is None:
        start = np.where(step < 0, np.iinfo(np.intp).max, 0)

    if stop is None:
        stop = np.where(step < 0, np.iinfo(np.intp).min, np.iinfo(np.intp).max)

    return _slice(a, start, stop, step)


Review comment (suggestion):
I would omit the last two comment lines.  Since this will be `stop is np._NoValue` I think it is clear from the code.  Feels more like an explanation of why we are changing it now.

Code after:
    Negative slices have the same meaning as in regular Python:

    >>> b = np.array(['hello world', 'γεια σου κόσμε', '你好世界', '👋 🌍'],
    ...              dtype=np.dtypes.StringDType())
    >>> np.strings.slice(b, -2)
    array(['hello wor', 'γεια σου κόσ', '你好', '👋'], dtype=StringDType())

    >>> np.strings.slice(b, -2, None)
    array(['ld', 'με', '世界', ' 🌍'], dtype=StringDType())

    >>> np.strings.slice(b, [3, -10, 2, -3], [-1, -2, -1, 3])
    array(['lo worl', ' σου κόσ', '世', '👋 🌍'], dtype=StringDType())

    >>> np.strings.slice(b, None, None, -1)
    array(['dlrow olleh', 'εμσόκ υοσ αιεγ', '界世好你', '🌍 👋'],
          dtype=StringDType())

    """
    # Just like in the construction of a regular slice object, if only start
    # is specified then start will become stop, see logic in slice_new.
    if stop is np._NoValue:
        stop = start
        start = None

    # adjust start, stop, step to be integers, see logic in PySlice_Unpack
    if step is None:
        step = 1
    step = np.asanyarray(step)
    if not np.issubdtype(step.dtype, np.integer):
        raise TypeError(f"unsupported type {step.dtype} for operand 'step'")
    if np.any(step == 0):
        raise ValueError("slice step cannot be zero")

    if start is None:
        start = np.where(step < 0, np.iinfo(np.intp).max, 0)

    if stop is None:
        stop = np.where(step < 0, np.iinfo(np.intp).min, np.iinfo(np.intp).max)

    return _slice(a, start, stop, step)