为什么排序列表检测在这种情况下不起作用?

Why sorted list detection does not work in this situation?

我的目标是让 python 代码能够检测列表是否已排序。

我想明白为什么下面的代码 return True 而不是我预期的猜测 False

l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
all(l[i] <= l[i+1] for i in xrange(len(l)-1)) # return "True"

备注:

为了理解这一点,我已经阅读(并测试)了以下主要两个信息 post:

编辑: 好的,显然问题仅出现在 iPython 中,而不是仅在使用 python 命令行时出现!

iPython 0.10

In [93]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]

In [94]: all(l[i] <= l[i+1] for i in xrange(len(l)-1))
Out[94]: True

python 2.6.4

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in xrange(len(l)-1))
False

我能够在我的机器上重现类似的问题。然而,经过挖掘,发现all函数不是内置函数而是来自numpy(all.__module__ == 'numpy.core.fromnumeric').

问题是您创建的是生成器而不是列表。例如:

all(x>5 for x in xrange(3))
# <generator object <genexpr> at 0x1153bf7d0>

all([x>5 for x in xrange(3)])
# False

if all(x>5 for x in xrange(3)):
   print True
else:
   print False
# prints True

if all([x>5 for x in xrange(3)]):
   print True
else:
   print False
# prints False

只需将 [...] 添加到您的表达式中:

all([l[i] <= l[i+1] for i in xrange(len(l)-1)])
# False

如果您确实需要创建一个列表,更有效的解决方案是执行一个简单的 for 循环:

for i in xrange(len(l)-1):
    if l[i] > l[i+1]:
        result = False
        break
else:
    result = True

如果像我一样,你覆盖了内置的 all 功能,你可以 del all 来恢复它。在那之后,你应该有 all.__module__ == '__builtin__'。如果还是不行,那就all = __builtin__.all

您在问题中提供的代码工作正常:

Python 2.7

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in xrange(len(l)-1))
False

Python 3.4

我们用 range 代替 xrange...

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in range(len(l)-1))
False

IPython 3.0.0 与 Python 2.7.6

In [1]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]

In [2]: all(l[i] <= l[i+1] for i in xrange(len(l)-1))
Out[2]: False

最后看来 iPython 0.10 中的可行解决方案是:

In [93]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
In [100]: all([l[i] <= l[i+1] for i in xrange(len(l)-1)])
Out[100]: False

编辑: 或者更好:使用已接受答案中提供的循环!