2017-02-20 61 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)