python 中的 If 语句仅通过改变条件的位置而工作不同

If statement in python working different just by changing position of condition

我刚刚在python遇到了一个奇怪的问题: 下面是合并排序算法的一个实现,如果我尝试 运行 它会给我一个索引错误。

def mergesort(s1,s2,S):
    i,j = 0,0
    while i+j < len(s1)+len(s2):
        if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):
            S.append(s1[i])
            i += 1
        else:
            S.append(s2[j])
            j += 1
    return S

s2 = [1,5,7]
s1 = [2,3,4,6,8]
S = []
print(mergesort(s1,s2,S))

这个程序的输出是:

Traceback (most recent call last):
  File "new.py", line 15, in <module>
    print(mergesort(s1,s2,S))
  File "new.py", line 4, in mergesort
    if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):
IndexError: list index out of range

现在只需在 if 语句中键入 j == len(s2),程序 运行 就完全没问题了:

def mergesort(s1,s2,S):
    i,j = 0,0
    while i+j < len(s1)+len(s2):
        if j == len(s2) or (i < len(s1) and s1[i] < s2[j]):
            S.append(s1[i])
            i += 1
        else:
            S.append(s2[j])
            j += 1
    return S

s2 = [1,5,7]
s1 = [2,3,4,6,8]
S = []
print(mergesort(s1,s2,S))

输出:[1, 2, 3, 4, 5, 6, 7, 8]

这真的让我感到惊讶,因为两个程序完全相同,但前一个给我一个错误。

此外,有问题的程序 运行 在 c++ 中没问题:

#include <iostream>

using namespace std;

int main() { 
    int s1[10] = { 2, 3, 4, 6, 8 }, s2[10] = { 1, 5, 7 }, s[20], i = 0, j = 0, x = 0;
    while (i + j < 8) {
        if ((i < 5 && s1[i] < s2[j]) || j == 3) {
            s[x++] = s1[i];
            i++;
        } else {
            s[x++] = s2[j];
            j++;
        }
    }
    for (int i = 0; i < 8; i++) {
        cout << s[i];
    }
     return 0;
}

输出:12345678

为什么在 python 运行 中给我错误的程序在 C++ 中完全正常? python 的 if 语句与 c++ 的 if 语句的工作方式不同吗?

第一个python程序确实不正确:如果j达到s2的长度,if (i < len(s1) and s1[i] < s2[j]) or j == len(s2):将导致越界访问s2[j]i 到达 s1 的末尾之前。

修复方法是在 (i < len(s1) and s1[i] < s2[j]) 之前测试 j == len(s2) (i < len(s1) and s1[i] < s2[j]),因为您自己已经正确地找到了。

C++程序有同样的问题,但C++不检测越界访问。阅读 s2[3] 只是具有未定义的行为,在您的情况下只是 returns 一个未指定的值。由于 j == 3,该测试无论如何都会评估为真,因此算法输出预期结果。

未定义的行为有时会产生预期的结果而不会引起注意。但是在较大的分配数组上使用该算法可能会产生明显的副作用,例如分段错误。