s[i:j:t] = t stipulation

N

Neil Cerutti

s[i:j:t] = t (1) t must have the same length as the slice it is
replacing.

Why?
.... while True:
.... yield 'a'
....
foo()
x = range(10)
x[::2] = foo()

This is infinite loop due to Python building a sequence out of
the iterator to check its length.

I think it might be more useful for

x[::2] = foo()

to result in an x of

['a', 1, 'a', 3, 'a', 5, 'a', 7, 'a', 9]

In other words, take (j-i)//k elements from t for abs(k) != 1.

A problem, though, arises when t is too short--the sequence
could be corrupted before an exception is thrown if you omit the
length check.

So you'd also have to define

x[::2] = 'aaa'

as resulting in

['a', 1, 'a', 2, 'a', 3, 5, 7, 9]

But perhaps that's just adding more useless complexity to the
already complex slicing rules (kudos for 'slice.indices', though
curses that the method isn't cross-referenced in more places).
 
T

Terry Reedy

| s[i:j:t] = t (1) t must have the same length as the slice it is
replacing.

This is essentially the same rule as requiring a proper length of t for

a,b,c = t # for whatever number of targets

And people have made similar suggestions as below for that case also.

| Why?

A mismatch could be intentional or accidental. In most cases of this sort,
Python assumes 'accident', especially when intent can easily be indicated
otherwise.

| >>> def foo():
| ... while True:
| ... yield 'a'
| ...
| >>> foo()
| >>> x = range(10)
| >>> x[::2] = foo()
|
| This is infinite loop due to Python building a sequence out of
| the iterator to check its length.
|
| I think it might be more useful for
|
| x[::2] = foo()
|
| to result in an x of
|
| ['a', 1, 'a', 3, 'a', 5, 'a', 7, 'a', 9]
|
| In other words, take (j-i)//k elements from t for abs(k) != 1.

Use the appropriate itertools function to take the proper number of
elements.

| A problem, though, arises when t is too short--the sequence
| could be corrupted before an exception is thrown if you omit the
| length check.
|
| So you'd also have to define
|
| x[::2] = 'aaa'
|
| as resulting in
|
| ['a', 1, 'a', 2, 'a', 3, 5, 7, 9]

No, it should be defined as resulting in

['a', 1, 'a', 2, 'a', 3, None, 5, None, 7, None, 9] # ;-)

Or better yet, require the programmer to specify by modifying either the
target or source spec, as is done now.

Terry Jan Reedy
 
N

Neil Cerutti

| s[i:j:t] = t (1) t must have the same length as the slice it is
replacing.

This is essentially the same rule as requiring a proper length
of t for

a,b,c = t # for whatever number of targets

And people have made similar suggestions as below for that case
also.

| Why?

A mismatch could be intentional or accidental. In most cases
of this sort, Python assumes 'accident', especially when intent
can easily be indicated otherwise.

Thanks. Assignment to slices are a convenient way to insert,
assign, and delete elements, but extended slices are only good
for assignment. Perhaps I was searching for consistency in the
wrong place, though.
| >>> def foo():
| ... while True:
| ... yield 'a'
| ...
| >>> foo()
| >>> x = range(10)
| >>> x[::2] = foo()
|
| This is infinite loop due to Python building a sequence out of
| the iterator to check its length.
|
| I think it might be more useful for
|
| x[::2] = foo()
|
| to result in an x of
|
| ['a', 1, 'a', 3, 'a', 5, 'a', 7, 'a', 9]
|
| In other words, take (j-i)//k elements from t for abs(k) != 1.

Use the appropriate itertools function to take the proper
number of elements.

And anyway my math was quite wrong. :(
| A problem, though, arises when t is too short--the sequence
| could be corrupted before an exception is thrown if you omit the
| length check.
|
| So you'd also have to define
|
| x[::2] = 'aaa'
|
| as resulting in
|
| ['a', 1, 'a', 2, 'a', 3, 5, 7, 9]

No, it should be defined as resulting in

['a', 1, 'a', 2, 'a', 3, None, 5, None, 7, None, 9] # ;-)

I thought deletion of elements would be more similar to slice
assignment, e.g.:

x[5:] = []
--> [0, 1, 2, 3, 4]
-/ /-> [0, 1, 2, 3, 4, None, None, None, None, None]
Or better yet, require the programmer to specify by modifying
either the target or source spec, as is done now.

It seems a shame to accept iterators but to build a sequence out
of them, if it can be avoided. But if there's too much confusion
about what it should mean, I guess that kills the idea.
 
T

Terry Reedy

| > No, it should be defined as resulting in
| >
| > ['a', 1, 'a', 2, 'a', 3, None, 5, None, 7, None, 9] # ;-)

Note smiley.

| I thought deletion of elements would be more similar to slice
| assignment, e.g.:
|
| x[5:] = []
| --> [0, 1, 2, 3, 4]
| -/ /-> [0, 1, 2, 3, 4, None, None, None, None, None]
|
| > Or better yet, require the programmer to specify by modifying
| > either the target or source spec, as is done now.
|
| It seems a shame to accept iterators but to build a sequence out
| of them, if it can be avoided. But if there's too much confusion
| about what it should mean, I guess that kills the idea.

For the core, we agree. For your personal use, completing
def repdel(museq, slise, source):
"Replace or delete museq[slise] with items from source"
...
with the behavior you want should not be too difficult.

tjr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top