问题
Consider the following piece of code:
def func1(a):
a[:] = [x**2 for x in a]
a = range(10)
print a #prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
func1(a[:5])
print a #also prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I wish to send a slice of the list a
and change it inside the function. My expected output is
[0, 1, 4, 9, 16, 5, 6, 7, 8, 9]
Which way is the idiomatic way to do so?
Thanks!
回答1:
If you slice the list, you modify only a copy, so what you want to do doesn't work in the form you want.
But you could pass an optional slice
object to func1
and if it's not None
, use it to perform the slice assignment (else use [:]
)
I would do the following (used a lambda
to avoid copy/paste of the formula and a generator expression to avoid creating a useless temporary list:
def func1(a,the_slice=None):
e = lambda y : (x**2 for x in y)
if the_slice:
a[the_slice] = e(a[the_slice])
else:
a[:] = e(a)
testing:
a = list(range(10))
func1(a)
print(a)
a = list(range(10))
func1(a,slice(5)) # stop at 5
print(a)
a = list(range(10))
func1(a,slice(5,len(a),2)) # start at 5 / stop at the end, stride/step 2
print(a)
result:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 25, 6, 49, 8, 81]
- in the first case, the totality of the list was changed
- in the second case, it only changed the first half.
- in the third case, it changed the second half, but 1 value out of 2 (stride=2)
回答2:
This will work:
a = range(10)
a[:5] = [c**2 for c in a[:5]]
回答3:
a[:5]
creates a new list. Hence, the changes that func1
applies to it are not mirrorred in a
. You could add the slicing to the function:
def func1(a, start=None, stop=None, step=None):
start = start if start is not None else 0
stop = stop if stop is not None else len(a)
step = step if step is not None else 1
a[start:stop:step] = [x**2 for x in a[start:stop:step]]
func1(a, stop=5)
来源:https://stackoverflow.com/questions/42346288/python-modifying-slice-of-list-in-function