Weired behaviour - The slice of empty string not return an error

dn PythonList at DancesWithMice.info
Mon Oct 31 00:05:44 EDT 2022


On 31/10/2022 03.59, Yassine Nasri wrote:
> PS: The ''[::] should  return an error logically.
> 
> Le dim. 30 oct. 2022 à 15:57, Yassine Nasri <yassine.naasri at gmail.com> a
> écrit :
> 
>> Hello,
>>
>> len('')  # => 0''[0]    # => error''[::]   # => ''''[::]   # <=> ''[0:len(''):1]
>>
>> the syntax of slice:
>>
>> slice(start, end, step)
>>
>> The start in ''[::] equivalent at index 0 of the ''
>>
>> Since the index 0 of '' returns an error.
>>
>> The ''[::] should not return an error logically.


Perhaps it will help to say:

- "indexing" one "element" from a "sequence" will yield a single result 
of the type of that element

- "slicing" a "sequence" will yield a result of the same type as the 
original sequence

The corollary to the first is expected: that if there is no element at 
the stated index/position, something is wrong.

However, what is not necessarily apparent, is that because the result is 
of the same type as the original sequence, and an empty-sequence is 
perfectly legal; so is it possible to slice something and receive back 
'nothing'.


The second 'saying' is to use the correct jargon:

- in a[ i ] i is an "index"

- in a[ i:j ] i and j are "parameters"

A parameter does not (also) need to be a legal index!


This is proven (as you have discovered (but is difficult to read, above):

 >>> sequence = []
 >>> len( sequence )
0
 >>> sequence[ 0 ]
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
IndexError: list index out of range
 >>> sequence[ 0:1 ]
[]


The question (and assertion) are discussed in the manual:
«Sequences

     These represent finite ordered sets indexed by non-negative 
numbers. The built-in function len() returns the number of items of a 
sequence. When the length of a sequence is n, the index set contains the 
numbers 0, 1, …, n-1. Item i of sequence a is selected by a[i].

     Sequences also support slicing: a[i:j] selects all items with index 
k such that i <= k < j. When used as an expression, a slice is a 
sequence of the same type. This implies that the index set is renumbered 
so that it starts at 0.

     Some sequences also support “extended slicing” with a third “step” 
parameter: a[i:j:k] selects all items of a with index x where x = i + 
n*k, n >= 0 and i <= x < j.
»

Thus, an index must point to an existing element, whereas the parameters 
of a slice need not. If the slice-specification calls for elements 
'beyond' the end of the sequence, then the result will only contain 
items up-to the last element, ie the length of the resultant-sequence 
will be shorter than j - i, where j > len( sequence ).


# Proof (which concurs with the OP's observations)

# playing with a tuple's indexes/indices

 >>> sequence = 1,2,3
 >>> sequence[ 1 ]
2

# notice the result's type!

 >>> sequence[ 9 ]
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

# the above index is plainly 'beyond' len( sequence )
# do you know about negative indexes/indices?

 >>> sequence[ -1 ]
3
 >>> sequence[ -9 ]
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

# again this index is 'beyond' the first element of the sequence


# let's play with some slicing;

 >>> sequence[ 0:3 ]
(1, 2, 3)
 >>> [ 1, 2, 3 ][ 0:3 ]
[1, 2, 3]

# same applies to lists (and strings, etc)
# notice the types!

 >>> sequence[ 1:1 ]
()
 >>> sequence[ 1:2 ]
(2,)
 >>> sequence[ -1:2 ]
()
 >>> sequence[ -1:-2 ]
()
 >>> sequence[ -1:-2:-1 ]
(3,)
 >>> sequence[ -1:-3:-1 ]
(3, 2)

# OK, what happens when parameters point to non-existent indexes?

 >>> sequence[ 1:9 ]
(2, 3)
 >>> sequence[ 1:-9 ]
()
 >>> sequence[ -1:-9:-1 ]
(3, 2, 1)
 >>> sequence[ -9:-1:-1 ]
()

# yes, they are parameters and not strictly indexes/indices!


https://docs.python.org/3/reference/datamodel.html?highlight=slicing#the-standard-type-hierarchy
for "sequences" and "slice objects"

Note that a Python set is "collection" but not a "sequence". Which means 
that neither indexing nor slicing (per above) will work on a set. We can 
ask if a particular value appears in a set ("contains") but cannot ask 
for the n-th element. To be able to index or slice it, a sequence must 
offer a __getitem__() method - tuple, list, and string do; but set does 
not. (check for yourself: help( set ) )

https://docs.python.org/3/library/collections.abc.html?highlight=collection

-- 
Regards,
=dn


More information about the Python-list mailing list