
Yanghao Hua writes:
For example, L[:] if appeared at the right hand side, means a copy (not a reference) of L, but now when appear on the left hand side, it behaves like an in-place copy. This two isn't it mentally contradicting each other?
No. I suspect you're confused by the specifics. Slice notation is fully general. L[m:m+k] specifies that a list operation will take place on the k elements starting with m. As a value, it makes a new list of references to those elements. As an assignment target, it deletes those elements and splices the sequence on the right hand side into L starting with m, "pushing m+k and following elements to the right".
The semantics of lvalues and rvalues are different in all languages I know of, and in this way. Slices are an unusual kind of lvalue, for sure, but once you've got the syntax, the semantics are pretty obvious and definitely useful.
You can write
L[n:n+1] = [x] instead of L[n] = x (only crazy people do that) L[n:n] = [x] instead of L.insert(n, x) (pretty crazy, too) L[n:n+1] = [] instead of del L[n] (only crazy people do that) L = []; [:] = [1, 2] (only crazy people do that, NB, this isn't "in-place" 'cause there's no "place" there to be "in"!) L[n:] = [] (useful, truncates to length n) L1[n:] = L2
The meaning of "L[:] = ..." is just the standard definition of slice as assignment target, with the endpoints defaulting to first and last. Since in your notation, the slice doesn't appear, no non-default slice assignment can even be expressed. For this purpose, "<==" is redundant and less powerful than "slice as left hand side" notation.
Any non-trivial left hand side can accept a right hand side of arbitrary length, the lengths don't have to match. And of course the right hand side can be a slice itself.