2017-02-20 33 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-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

你可以分配給一個slice,但是這並不改變'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

結果:

[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)