​What little documentation I could find, providing a stride on the assignment target for a list is supposed to trigger 'advanced slicing' causing element-wise replacement - and hence requiring that the source iterable has the appropriate number of elements.
>>> a = [0,1,2,3] >>> a[::2] = [4,5] >>> a [4, 1, 5, 3] >>> a[::2] = [4,5,6] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: attempt to assign sequence of size 3 to extended slice of size 2 This is in contrast to regular slicing (*without* a stride), allowing to replace a *range* by another sequence of arbitrary length. >>> a = [0,1,2,3] >>> a[:3] = [4] >>> a [4, 3] Issue ===== When, however, a stride of `1` is specified, advanced slicing is not triggered. >>> a = [0,1,2,3] >>> a[:3:1] = [4] >>> a [4, 3] If advanced slicing had been triggered, there should have been a ValueError instead. Expected behaviour: >>> a = [0,1,2,3] >>> a[:3:1] = [4] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: attempt to assign sequence of size 1 to extended slice of size 3 I think that is an inconsistency in the language that should be fixed. Why do we need this? ==================== One may want this as extra check as well so that list does not change size. Depending on implementation, it may come with performance benefits as well. One could, though, argue that you still get the same result if you do all correctly >>> a = [0,1,2,3] >>> a[:3:1] = [4,5,6] >>> a [4, 5, 6, 3] But I disagree that there should be no error when it is wrong. *Strides that are not None should always trigger advanced slicing.* Other Data Types ================ This change should also be applied to bytearray, etc., though see below. Concerns ======== It may break some code that uses advanced slicing and expects regular slicing to occur? These cases should be rare, and the error message should be clear enough to allow fixes? I assume these cases should be exceptionally rare. If the implementation relies on `slice.indices(len(seq))[2] == 1` to determine about advance slicing or not, that would require some refactoring. If it is only `slice.stride in (1, None)` then this could easily replaced by checking against None. Will there be issues with syntax consistency with other data types, in particular outside the core library? - I always found that the dynamic behaviour of lists w/r non-advanced slicing to be somewhat peculiar in the first place, though, undeniably, it can be immensely useful. - Most external data types with fixed memory such as numpy do not have this dynamic flexibility, and the behavior of regular slicing on assignment is the same as regular slicing. The proposed change would increase consistency with these other data types. More surprises ============== >>> import array >>> a[1::2] = a[3:3] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: attempt to assign sequence of size 0 to extended slice of size 2 whereas >>> a = [1,2,3,4,5] >>> a[1::2] = a[3:3] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: attempt to assign sequence of size 0 to extended slice of size 2 >>> a = bytearray(b'12345') >>> a[1::2] = a[3:3] >>> a bytearray(b'135') but numpy >>> import numpy as np >>> a = np.array([1,2,3,4,5]) >>> a[1::2] = a[3:3] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: could not broadcast input array from shape (0) into shape (2) and >>> import numpy as np >>> a[1:2] = a[3:3] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: could not broadcast input array from shape (0) into shape (1) The latter two as expected. memoryview behaves the same. Issue 2 ======= Whereas NumPy is know to behave differently as a data type with fixed memory layout, and is not part of the standard library anyway, the difference in behaviour between lists and arrays I find disconcerting. This should be resolved to a consistent behaviour. Proposal 2 ========== Arrays and bytearrays should should adopt the same advanced slicing behaviour I suggest for lists. Concerns 2 ========== This has the potential for a lot more side effects in existing code, but as before in most cases error message should be triggered. Summary ======= I find it it not acceptable as a good language design that there is a large range of behaviour on slicing in assignment target for the different native (and standard library) data type of seemingly similar kind, and that users have to figure out for each data type by testing - or at the very least remember if documented - how it behaves on slicing in assignment targets. There should be a consistent behaviour at the very least, ideally even one with a clear user interface as suggested for lists. -Alexander
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/