gpt4 book ai didi

python - 为什么 Python 将 None 插入到切片步骤中?

转载 作者:太空狗 更新时间:2023-10-30 01:23:53 25 4
gpt4 key购买 nike

这可以通过示例进行最好的说明(所有示例都假定导入了 ast;请注意,我使用的是 Python 2.7.1):

# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=None)
ast.dump(ast.parse("l[1:10]").body[0].value.slice)

# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1:10:]").body[0].value.slice)

# Outputs: Slice(lower=Num(n=1), upper=None, step=None)
ast.dump(ast.parse("l[1:]").body[0].value.slice)

# Outputs: Slice(lower=None, upper=None, step=None)
ast.dump(ast.parse("l[:]").body[0].value.slice)

因此,正如我们所见,l[1:10] 产生一个 AST 节点,其切片有两个子节点——lowerupper 都设置为数字字面量——以及一个空的第三个 step 子级。但是我们认为相同的 [1:10:] 将其切片的 step 子级设置为 None 文字表达式(Name(id='None', ctx=Load())).

好吧,我想。也许 Python 将 l[1:10:]l[1:10] 视为完全不同的表达式。 Python 表达式引用(link)似乎确实表明了这一点; l[1:10] 是一个简单的切片,而 l[1:10:] 是一个扩展切片(只有一个切片项)。

但是,即使在扩展切片的上下文中,step 参数也会被特殊处理。如果我们尝试忽略带有一个切片项的扩展切片中的上限或下限,我们最终只会得到空的子项:

# Outputs: Slice(lower=Num(n=1), upper=None, step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1::]").body[0].value.slice)

# Outputs: Slice(lower=None, upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[:10:]").body[0].value.slice)

此外,经过进一步检查,AST 甚至没有将这些切片视为扩展切片。这是扩展切片的实际样子:

# Outputs: ExtSlice(dims=[Slice(lower=None, upper=None, step=Name(id='None', ctx=Load())), Slice(lower=None, upper=None, step=Name(id='None', ctx=Load()))])
ast.dump(ast.parse("l[::, ::]").body[0].value.slice)

所以这是我的结论:AST 总是出于某种原因将 step 参数视为特殊参数,而与此无关的是,Slice AST 节点代表一个长切片(我猜是这样不必有两个不同的 Slice 基类——ShortSliceLongSlice——尽管我认为这是首选)等等单项扩展切片可以表示为普通 Slice 节点,出于某种原因这样做。允许将 None 参数解释为默认值对我来说似乎是错误的,但我知道这是一个有目的的设计决定; None 文字插入和将长切片视为 Slice 节点似乎有点像意外(或旧设计的产物)。

还有其他人有更明智的解释吗?

最佳答案

如果在扩展切片符号中没有这样的处理,你将无法区分 l[1:]l[1::],你也不能t 调用不同的特殊方法 - __getslice__ 可以为普通切片调用,但 __getitem__ 必须为扩展切片调用。

所以它主要是 Python 2.x 的向后兼容性,它在 Python 3.x 中消失了:

Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ast
>>> ast.dump(ast.parse("l[1:]").body[0].value.slice)
'Slice(lower=Num(n=1), upper=None, step=None)'
>>> ast.dump(ast.parse("l[1::]").body[0].value.slice)
'Slice(lower=Num(n=1), upper=None, step=None)'
>>>

参见 python2.7 source for ast.cdata model description了解更多信息。

关于python - 为什么 Python 将 None 插入到切片步骤中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8440248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com