Python: for x in A[1:] 的意思是什么?

20

我正在尝试从维基百科理解卡登算法,然后我发现了这个:

def max_subarray(A):
    max_ending_here = max_so_far = A[0]
    for x in A[1:]:
        max_ending_here = max(x, max_ending_here + x)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

我不熟悉Python。我试图通过谷歌搜索这个语法的含义,但由于不知道这个语法叫什么,所以我找不到正确答案。但是,我发现A[1:]相当于省略了A[0],所以我认为for x in A[1:]:与Java中的for(int i = 1; i < A.length; i++)等价。

但是,当我把for x in A[1:]:改成for x in range(1,len(A))后,结果错误了。

如果这是一个愚蠢的问题,那么请原谅我,但我不知道在哪里可以找到答案。有人能告诉我这个语法的含义和它被称作什么吗?此外,你能否给我在Java中for x in A[1:]:的等价写法?

6个回答

41

这是我尝试过的一些示例。

>>> a=[1,5,9,11,2,66]

>>> a[1:]
[5, 9, 11, 2, 66]

>>> a[:1]
[1]

>>> a[-1:]
[66]

>>> a[:-1]
[1, 5, 9, 11, 2]

>>> a[3]
11

>>> a[3:]
[11, 2, 66]

>>> a[:3]
[1, 5, 9]

>>> a[-3:]
[11, 2, 66]

>>> a[:-3]
[1, 5, 9]

>>> a[::1]
[1, 5, 9, 11, 2, 66]

>>> a[::-1]
[66, 2, 11, 9, 5, 1]

>>> a[1::]
[5, 9, 11, 2, 66]

>>> a[::-1]
[66, 2, 11, 9, 5, 1]

>>> a[::-2]
[66, 11, 5]

>>> a[2::]
[9, 11, 2, 66]

我认为通过这些例子,你可以更好地理解。


14

这是 数组切片 语法。查看此 Stack Overflow 问题:解释 Python 的切片符号

对于一个对象列表 my_list,例如 [1, 2, "foo", "bar"]my_list[1:] 等同于从索引为 0 的位置开始的所有元素的浅拷贝列表:[2, "foo", "bar"]。因此,您的 for 循环将遍历这些对象:

for-iteration 0: x == 2 
for-iteration 1: x == "foo" 
for-iteration 2: x == "bar" 

range(..) 返回一个索引(整数)列表/生成器,因此你的for语句将迭代整数 [1, 2, ..., len(my_list)]

for-iteration 0: x == 1 
for-iteration 1: x == 2
for-iteration 2: x == 3
所以在后面的版本中,您可以使用x作为列表的索引:iter_obj = my_list[x]
或者,如果仍然需要迭代索引(例如用于当前对象的“计数”),则稍微更加 Pythonic 的方法是使用enumerate
for (i, x) in enumerate(my_list[1:]):
    # i is the 0-based index into the truncated list [0, 1, 2]
    # x is the current object from the truncated list [2, "foo", "bar"]

如果您决定将my_list的类型更改为其他内容,则此版本稍微具有更好的适应性,因为它不依赖于从0开始编号的实现细节,因此更有可能与支持切片语法的其他可迭代类型一起使用。


哦,我明白了。当我将 for x in A[1:] 更改为 for x in range(1, len(A)) 时,我应该使用 A[x] 而不仅仅是 x 来访问元素。在 for x in A[1:]: doSomething(x)for x in range(1, len(A)): doSomething(A[x]) 之间有什么区别吗? - Margo Eastham
@MargoEastham,是的,你可以使用A[x]。如果您想要将索引用于其他内容,则可能希望这样做。前一种语法被认为更具“Python风格”,而后者则更冗长。前一种方法(迭代对象)可能更适合与支持切片语法的列表以外的对象一起使用。后一种版本假定通过基于0的整数索引进入集合。但实际上,这不应该有任何区别。它更多关于类型依赖性/假设和代码清晰度。 - Preet Kukreti
谢谢。现在我知道这都是关于什么的了。 - Margo Eastham
注意,你可以提供一个可选的第二个参数给enumerate函数来指定起始索引。因此, for i, x in enumerate(my_list[1:], 1): 将会从1开始计数。 - PM 2Ring

2

"for x in A[1:]"是什么意思?

这个问题有两部分。首先,让我们考虑A[1:],它是对列表或数组的切片符号。考虑以下列表:

A = [3,4,5,6]

在这个例子中,A[0]是3,A[1]是4,以此类推。当使用:时,可以表示获取所有内容或从特定索引开始的内容。因此,A[1:]是切片符号,表示“获取列表的第1个元素到最后一个元素”。因此,在我的简单示例中,A[1:]给出了一个列表的片段,即[4,5,6]
问题的第二部分涉及for x...部分。在此情况下,这是Python表示法,表示对列表中的每个元素进行操作。因此:
A = [3,4,5,6]
for x in A[1:]:  #remember A[1:] is [4,5,6]
    print(x)

这将在第一次循环时打印4,在第二次循环时打印5,在第三次循环时打印6。

2

与其他语言不同,Python中迭代序列会产生序列本身内的元素。这意味着在[1, 2, 4]上进行迭代会依次产生124,而不是012


1
在Java中也有for(int x : A),其中A是一个整型数组int[]。你能解释一下 for x in Afor x in A[1:] 之间的区别吗?如果 A[1:] 表示第 1 个元素到最后一个元素(不包括零号元素),那么 for x in A[1:] 就只是从第 1 个元素到最后一个元素进行迭代(忽略元素 A[0])吗? - Margo Eastham
@MargoEastham 是的,就是这样。 - Waleed Khan
1
你不是因为切片会给你任何特定的好处而对序列进行切片,而是因为算法要求你对除第一个元素以外的所有元素进行操作。 - Ignacio Vazquez-Abrams
我并不认为“与其他语言不同”这个说法是恰当的,因为许多其他语言都包含类似的结构,即使是备受尊崇的C++现在也有一个。有意义的说法应该是Python没有来自C系列语言的传统“通用for循环”,它允许你做任何想做的事情。 - Rufflewind
@IgnacioVazquez-Abrams:无论这是否正确与此问题无关。 - Rufflewind
显示剩余3条评论

1
A = [1, 2, 3]

A[1:] == [2, 3]

这用于从第一个元素开始截断列表。
请注意,列表是可变的。如果您发现像A [:]这样的内容,那么意味着他们想要创建该列表的副本,而不更改原始列表,并使用A [::-1]来反转列表,而不是使用reversed(A)

0

简单来说,A[1:] 表示访问从第一个位置开始的元素(不包括 A[0])。这是我们需要考虑的唯一逻辑。

A=[23,45,6,77,456,3]
print(A[1:])

输出:

45,6,77,456,3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接