<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Feb 22, 2018 at 2:18 PM, Alexander Heger <span dir="ltr"><<a href="mailto:python@2sn.net" target="_blank">python@2sn.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-family:monospace,monospace">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.</div><div style="font-family:monospace,monospace"><br></div><div><div style="font-family:monospace,monospace">>>> a = [0,1,2,3]</div><div style="font-family:monospace,monospace">>>> a[::2] = [4,5]</div><div style="font-family:monospace,monospace">>>> a</div><div style="font-family:monospace,monospace">[4, 1, 5, 3]</div><div style="font-family:monospace,monospace">>>> a[::2] = [4,5,6]</div><div style="font-family:monospace,monospace">Traceback (most recent call last):</div><div style="font-family:monospace,monospace"> File "<stdin>", line 1, in <module></div><div style="font-family:monospace,monospace">ValueError: attempt to assign sequence of size 3 to extended slice of size 2</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">This is in contrast to regular slicing (*without* a stride), allowing to replace a *range* by another sequence of arbitrary length.</div><div style="font-family:monospace,monospace"><br></div><div><div><font face="monospace, monospace">>>> a = [0,1,2,3]</font></div><div><font face="monospace, monospace">>>> a[:3] = [4]</font></div><div><font face="monospace, monospace">>>> a</font></div><div><font face="monospace, monospace">[4, 3]</font></div></div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">Issue</div><div style="font-family:monospace,monospace">=====</div><div style="font-family:monospace,monospace">When, however, a stride of `1` is specified, advanced slicing is not triggered.</div><div style="font-family:monospace,monospace"><br></div><div><div style="font-family:monospace,monospace">>>> a = [0,1,2,3]</div><div style="font-family:monospace,monospace">>>> a[:3:1] = [4]</div><div style="font-family:monospace,monospace">>>> a</div><div style="font-family:monospace,monospace">[4, 3]</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">If advanced slicing had been triggered, there should have been a ValueError instead. </div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">Expected behaviour:</div><div style="font-family:monospace,monospace"><br></div><div><div><font face="monospace, monospace">>>> a = [0,1,2,3]</font></div><div><font face="monospace, monospace">>>> a[:3:1] = [4]</font></div><div><div><font face="monospace, monospace">Traceback (most recent call last):</font></div><div><font face="monospace, monospace"> File "<stdin>", line 1, in <module></font></div><div><font face="monospace, monospace">ValueError: attempt to assign sequence of size 1 to extended slice of size 3</font></div></div></div><div><br></div><div style="font-family:monospace,monospace">I think that is an inconsistency in the language that should be fixed.</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">Why do we need this?</div><div style="font-family:monospace,monospace">====================</div><div style="font-family:monospace,monospace">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.</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">One could, though, argue that you still get the same result if you do all correctly</div><div style="font-family:monospace,monospace"><br></div><div><div style="font-family:monospace,monospace">>>> a = [0,1,2,3]</div><div style="font-family:monospace,monospace">>>> a[:3:1] = [4,5,6]</div><div><div><font face="monospace, monospace">>>> a</font></div><div><font face="monospace, monospace">[4, 5, 6, 3]</font></div></div><div style="font-family:monospace,monospace"><br></div></div><div style="font-family:monospace,monospace">But I disagree that there should be no error when it is wrong. </div><div style="font-family:monospace,monospace">*Strides that are not None should always trigger advanced slicing.*</div></div></div></div></blockquote><div><br></div><div>This makes sense.<br><br>(I wonder if the discrepancy is due to some internal interface that loses the distinction between None and 1 before the decision is made whether to use advanced slicing or not. But that's a possible explanation, not an excuse.)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div style="font-family:monospace,monospace">Other Data Types</div><div style="font-family:monospace,monospace">================</div><div style="font-family:monospace,monospace">This change should also be applied to bytearray, etc., though see below.</div></div></div></div></blockquote><div><br></div><div>Sure.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div style="font-family:monospace,monospace">Concerns</div><div style="font-family:monospace,monospace">========</div><div style="font-family:monospace,monospace">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.</div></div></div></div></blockquote><div><br></div><div>Yeah, backwards compatibility sometimes prevents fixing a design bug. I don't know if that's the case here, we'll need reports from real-world code.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div style="font-family:monospace,monospace">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.</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">Will there be issues with syntax consistency with other data types, in particular outside the core library? </div></div></div></div></blockquote><div><br></div><div>Things outside the stdlib are responsible for their own behavior. Usually they can move faster and with less worry about breaking backward compatibility.<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div style="font-family:monospace,monospace"> </div><div style="font-family:monospace,monospace">- 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. </div></div></div></div></blockquote><div><br></div><div>If you're talking about the ability to resize a list by assigning to a slice, that's as intended. It predates advanced slicing by a decade or more.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div style="font-family:monospace,monospace">- 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.</div></div></div></div></blockquote><div><br></div><div>How? Resizing through slice assignment will stay for builtin types -- if numpy doesn't support that, so be it.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div style="font-family:monospace,monospace">More surprises</div><div style="font-family:monospace,monospace">==============</div><div><div style="font-family:monospace,monospace">>>> import array</div><div><div><font face="monospace, monospace">>>> a[1::2] = a[3:3]</font></div><div><font face="monospace, monospace">Traceback (most recent call last):</font></div><div><font face="monospace, monospace"> File "<stdin>", line 1, in <module></font></div><div><font face="monospace, monospace">ValueError: attempt to assign sequence of size 0 to extended slice of size 2</font></div></div><div style="font-family:monospace,monospace"><br></div></div><div style="font-family:monospace,monospace">whereas</div><div style="font-family:monospace,monospace"><br></div><div><div style="font-family:monospace,monospace">>>> a = [1,2,3,4,5]</div><div style="font-family:monospace,monospace">>>> a[1::2] = a[3:3]</div><div style="font-family:monospace,monospace">Traceback (most recent call last):</div><div style="font-family:monospace,monospace"> File "<stdin>", line 1, in <module></div><div style="font-family:monospace,monospace">ValueError: attempt to assign sequence of size 0 to extended slice of size 2</div></div></div></div></blockquote><div><br></div><div>OK, so array doesn't use the same rules. That should be fixed too probably (assuming whatever is valid today remains valid).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><font face="monospace, monospace">>>> a = bytearray(b'12345')</font></div><div><span style="font-family:monospace,monospace">>>> a[1::2] = a[3:3]</span><br></div><div><font face="monospace, monospace">>>> a</font></div><div><font face="monospace, monospace">bytearray(b'135')</font></div></div></div></div></div></blockquote><div><br></div><div>Bytearray should also follow the same rules.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div style="font-family:monospace,monospace">but numpy</div><div style="font-family:monospace,monospace"><br></div><div><div style="font-family:monospace,monospace">>>> import numpy as np</div><div style="font-family:monospace,monospace">>>> a = np.array([1,2,3,4,5])</div><div style="font-family:monospace,monospace">>>> a[1::2] = a[3:3]<br></div><div style="font-family:monospace,monospace">Traceback (most recent call last):</div><div style="font-family:monospace,monospace"> File "<stdin>", line 1, in <module></div><div style="font-family:monospace,monospace">ValueError: could not broadcast input array from shape (0) into shape (2)</div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">and</div><div style="font-family:monospace,monospace"><br></div><div><div><font face="monospace, monospace">>>> import numpy as np</font></div><div><font face="monospace, monospace">>>> a[1:2] = a[3:3]</font></div><div><font face="monospace, monospace">Traceback (most recent call last):</font></div><div><font face="monospace, monospace"> File "<stdin>", line 1, in <module></font></div><div><font face="monospace, monospace">ValueError: could not broadcast input array from shape (0) into shape (1)</font></div></div><div style="font-family:monospace,monospace"><br></div></div><div style="font-family:monospace,monospace">The latter two as expected. memoryview behaves the same.</div></div></div></blockquote><div><br></div><div>Let's leave numpy out of this discussion. And memoryview is a special case because it can't change size (it provides a view into an inflexible structure).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div style="font-family:monospace,monospace">Issue 2</div><div style="font-family:monospace,monospace">=======</div><div style="font-family:monospace,monospace">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. </div><div style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace">Proposal 2</div><div style="font-family:monospace,monospace">==========</div><div style="font-family:monospace,monospace">Arrays and bytearrays should should adopt the same advanced slicing behaviour I suggest for lists.</div></div></div></blockquote><div><br></div><div>Sure.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div style="font-family:monospace,monospace">Concerns 2</div><div style="font-family:monospace,monospace">==========</div><div style="font-family:monospace,monospace">This has the potential for a lot more side effects in existing code, but as before in most cases error message should be triggered.</div></div></div></blockquote><div><br></div><div>Side effects? No code that currently doesn't raise will break, right?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div style="font-family:monospace,monospace">Summary</div><div style="font-family:monospace,monospace">=======</div><div style="font-family:monospace,monospace">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.</div></div></div></blockquote><div><br></div><div>Fortunately, what *you* find acceptable or good language design is not all that important. (You can avoid making any mistakes in your own language. :-) You may by now realize that 100% consistent behavior is hard to obtain. However we'll gladly consider your feedback.<br></div></div><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div>