【问题标题】:Why does `for x in list[None:None]:` work?为什么`for x in list[None:None]:`有效?
【发布时间】:2014-05-19 22:43:45
【问题描述】:

我有一个脚本尝试通过二分搜索读取子集的开始点和结束点,然后使用这些值创建切片以进行进一步处理。

我注意到当这些变量没有设置时(搜索返回 None),代码仍然会运行,最后我注意到从 None 到 None 的切片就像检查整个列表一样工作(见下面的例子) .

#! /usr/bin/env python
list = [1,2,3,4,5,6,7,8,9,10]
for x in list[None:None]:
  print x

有谁知道为什么选择将list[None:None] 简单地视为list[:],至少我认为会发生这种情况(如果我错了,请纠正我)。我个人认为在这种情况下抛出 TypeError 是可取的。

【问题讨论】:

  • 我怀疑这个选择实际上是将list[:] 视为list[None:None]
  • 可能正是您的用例。如果您从其他地方设置了startend 点,如果list[None:None] 不起作用,那么您将没有恢复的机会。这样你就可以提前测试if not any(x is None for x in [start,end]):

标签: python slice


【解决方案1】:

因为None 是切片位置的默认值。您可以使用None 或完全省略该值,此时会为您传入None

None 是默认值,因为您可以使用负跨度,此时默认的开始和结束位置会更改。例如,比较 list[0:len(list):-1]list[None:None:-1]

Python 在整个标准库中使用None 表示“未指定值”;这也不例外。

请注意,如果您的类实现了 object.__getitem__ hook,您将获得一个 slice() 对象,其中 start、end 和 stride 属性也设置为 None

>>> class Foo(object):
...     def __getitem__(self, key):
...         print key
... 
>>> Foo()[:]
slice(None, None, None)

由于Foo() 甚至没有实现__len__,因此默认使用None 在这里是完全合乎逻辑的。

【讨论】:

  • 我将不得不让我的二进制搜索函数返回 None 以外的东西。感谢您的详细说明。
  • @BasJansen 您可以测试None:None 的结果,也可以抛出异常。两者都非常Pythonic。使用特殊的“魔法”值通常不是一个好的选择。
  • @BasJansen 搜索函数应该返回与搜索相关的值,而不是基于您将如何在搜索之外使用它们(例如,不要返回(0, 0),这样您将得到一个空切片[0:0],如果零不是逻辑搜索结果)。更好的解决方案是在尝试切片之前检查 Nones。
【解决方案2】:

None 是“未给出参数”的常用表示,因此您可以将事实传达给函数。你会经常看到这样声明的函数或方法

def f(p=None):
    if f is None:
        f = some_default_value()

我想这让选择很明确:使用None 你可以告诉切片器使用它的默认值。

【讨论】:

    【解决方案3】:

    我也认为list[None:None] 被解释为list[:]。这是一种方便的行为,因为您可以执行以下操作:

    return list[some_params.get('start'):some_params.get('end')]
    

    如果列表切片不适用于None,您必须自己检查startend 是否为None

    if some_params.get('start') and some_params.get('end'):
        return list[some_params.get('start'):some_params.get('end')]
    elif some_params.get('start'):
        return list[some_params.get('start'):]
    elif end:
        return list[:some_params.get('end')]
    else:
        return list[:]
    

    幸运的是,Python 中不是这种情况:)。

    【讨论】:

    • 我期待两个相同变量之间的切片为 0,但从我的问题和后续答案中可以清楚地看出,它被视为“默认”或“未指定”。
    • 可以打高尔夫球到return list[some_params.get('start'):some_params.get('end')]
    猜你喜欢
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多