Why are snippets in Python 3 still copied rather than views?

As I noticed only after commenting on this answer , fragments in Python 3 return small copies of what they chop, not views. Why is this so? Even leaving aside the excessive use of views, rather than cutting copies, the fact that dict.keys , dict.values and dict.items all return views in Python 3 and that there are many other aspects of Python 3 that are more widely used by iterators, it seems that there would be a movement towards making the slices look alike. itertools has an islice function that makes iterative slices, but which is more limited than regular slicing, and does not provide dict.keys or dict.values line-of- dict.keys dict.values .

Also, the fact that you can use slice assignment to modify the original list, but the fragments themselves are copies, not representations, is a controversial aspect of the language and seems to violate some of the principles illustrated in Zen of Python .

That is, you can do

 >>> a = [1, 2, 3, 4, 5] >>> a[::2] = [0, 0, 0] >>> a [0, 2, 0, 4, 0] 

But not

 >>> a = [1, 2, 3, 4, 5] >>> a[::2][0] = 0 >>> a [0, 2, 3, 4, 5] 

or something like

 >>> a = [1, 2, 3, 4, 5] >>> b = a[::2] >>> b view(a[::2] -> [1, 3, 5]) # numpy doesn't explicitly state that its slices are views, but it would probably be a good idea to do it in some way for regular Python >>> b[0] = 0 >>> b view(a[::2] -> [0, 3, 5]) >>> a [0, 2, 3, 4, 5] 

Seems somewhat arbitrary / unwanted.

I know http://www.python.org/dev/peps/pep-3099/ and the part that says: "Slices and extended slices will not disappear (even if the __getslice__ and __setslice__ APIs can be replaced), as well will not return views for standard object types. ", but the related discussion does not mention why it was decided to cut with views; in fact, most of the comments on this particular proposal from the proposals listed in the initial communication seemed to be positive.

What prevented the implementation of something similar in Python 3.0, which was specially designed so as not to be strictly compatible with Python 2.x and, thus, would be the best time to implement such a design change, and is there anything that could prevent it in future versions of Python?

+45
python language-design slice
Aug 01 2018-11-11T00:
source share
2 answers

Well, it looks like I have found a lot of arguments in favor of resolving opinions going downstream, starting with http://mail.python.org/pipermail/python-3000/2006-August/003224.html (this is primarily about but by at least one email in the stream mentions mutable objects such as lists), as well as some things from:

http://mail.python.org/pipermail/python-3000/2007-February/005739.html
http://mail.python.org/pipermail/python-dev/2008-May/079692.html and email in the stream

It looks like the benefits of switching to this style for basic Python will be far outweighed by the complexity and various undesired edge cases. Oh good.

... And when I started thinking about the possibility of simply replacing the current slice path, objects are processed using the iterative form a la itertools.islice , like zip , map , etc. everyone returns iterables instead of lists in Python 3, I began to realize all the unexpected behavior and possible problems that may arise from this. Looks like it could be a dead end now.

On the plus side, numpy arrays are quite flexible, so in situations where it might be necessary, it would not be too difficult to use one-dimensional ndarrays instead of lists. However, it seems that ndarrays do not support the use of slicing to insert additional elements into arrays, as is the case with Python lists:

 >>> a = [0, 0] >>> a[:1] = [2, 3] >>> a [2, 3, 0] 

I think the numpy equivalent would look something like this:

 >>> a = np.array([0, 0]) # or a = np.zeros([2]), but that not important here >>> a = np.hstack(([2, 3], a[1:])) >>> a array([2, 3, 0]) 

A slightly more complicated case:

 >>> a = [1, 2, 3, 4] >>> a[1:3] = [0, 0, 0] >>> a [1, 0, 0, 0, 4] 

against

 >>> a = np.array([1, 2, 3, 4]) >>> a = np.hstack((a[:1], [0, 0, 0], a[3:])) >>> a array([1, 0, 0, 0, 4]) 

And, of course, the numpy examples above do not store the result in the original array, as happens with the usual Python list extension.

+2
Aug 4 '11 at 16:12
source share

Also, the fact that you can use the slice assignment to modify the original list, but the fragments themselves are copies, not representations.

Hmm .. this is not entirely correct; although I can see how you can think it. In other languages, the purpose of the slice, for example:

 a[b:c] = d 

equivalently

 tmp = a.operator[](slice(b, c)) # which returns some sort of reference tmp.operator=(d) # which has a special meaning for the reference type. 

But in python, the first statement actually translates to this:

 a.__setitem__(slice(b, c), d) 

Which means that the assignment of an element is actually specifically recognized in python in order to have special meaning, separate from the search and assignment of an element; they may be unrelated. This is consistent with python in general, since python does not have concepts such as "lvalues" found in C / C ++; It is not possible to overload the assignment operator itself; only specific cases where the left side of the job is not a simple identifier.

Suppose the lists had views; And you tried to use it:

 myView = myList[1:10] yourList = [1, 2, 3, 4] myView = yourList 

In languages ​​other than python, there might be a way to drag yourList to myList , but in python, since the name myView appears as a bare identifier, this can only mean the assignemnt variable; performance lost.

+10
Aug 01 '11 at 18:56
source share



All Articles