2017-02-20 25 views
2

Рассмотрим следующий фрагмент кода:питон Изменение кусочком списка в функции

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] 

Я хотел бы послать срез списка a и изменить его внутри функции. Мой ожидаемый результат:

[0, 1, 4, 9, 16, 5, 6, 7, 8, 9] 

Каким путем является идиоматический способ сделать это?

Спасибо!

+0

Вы также можете проверить это http://stackoverflow.com/questions/22054698/python-modifying -list-inside-a-function – Kasramvd

+0

@ Kasramvd Поскольку у другого вопроса нет разреза, я не считаю, что это дубликаты. Спасибо за ссылку в любом случае ... – omerbp

+0

Это тривиальное различие, но главная проблема заключается в том, что изменение изменчивого объекта внутри функции может отражать вызывающего. – Kasramvd

ответ

0

Это будет работать:

a = range(10) 

a[:5] = [c**2 for c in a[:5]] 
+0

спасибо, я представил этот пример игрушек как средство выражения моей более крупной проблемы, поэтому этот простой ответ на самом деле не помогает ... – omerbp

0

a[:5] создает новый список. Следовательно, изменения, которые применяется к нему func1, не отражены в a. Вы можете добавить нарезку функции:

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) 
+0

Разве нет возможности реализовать эту идею, не испортив ее индексами? – omerbp

+1

Вы можете назначить срез, но это не меняет того факта, что 'fnc1 (a [: 5])' передает список 'fnc1', который ничего не знает об исходном' a'. – schwobaseggl

2

Если вы отрезаете список, вы изменяете только копию, так что вы хотите сделать, не работает в форме вы хотите.

Но вы могли бы пройти дополнительный slice объект func1, и если это не None, использовать его для выполнения задания среза (иначе использовать [:])

Я хотел бы сделать следующее (используется lambda, чтобы избежать копирования/вставки формулы и выражения генератора, чтобы не создавать бесполезное временный список:

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) 

испытания:

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) 

результат:

[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] 
  • в первом случае, совокупность списка был изменен
  • во втором случае, он только изменил первую половину.
  • в третьем случае, она изменила вторую половину, но 1 значение из 2 (шаг = 2)