这可以通过示例进行说明(所有示例都假定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节点,其切片有两个子节点 - lower
和upper
都设置为数字文字 - 而空的第三个{{1}孩子。但我们认为相同的step
将其切片的[1:10:]
子项设置为step
文字表达式(None
)。
好的,我想。也许Python将Name(id='None', ctx=Load())
和l[1:10:]
视为完全不同的表达式。 Python表达式引用(link)当然似乎表明了这一点; l[1:10]
是一个简单的切片,但l[1:10]
是一个扩展切片(只有一个切片项)。
但是,即使在扩展切片的上下文中,也会特别处理step参数。如果我们尝试用一个切片项忽略扩展切片中的上限或下限,我们最终会得到空子:
l[1:10:]
此外,经过进一步检查,AST甚至不会将这些切片视为延长切片。这是扩展切片的实际情况:
# 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)
参数视为特殊的,并且无关地,step
AST节点表示一个长切片(我想所以没有必要是两个不同的基类Slice
类 - Slice
和ShortSlice
- 虽然我认为这是首选的)因此单项扩展切片可以表示为正常{{1}由于某种原因,节点已完成。允许LongSlice
参数被解释为默认值似乎是错误的,但我理解这是一个有目的的设计决策;将Slice
文字插入和处理长切片视为None
节点似乎有点像事故(或旧设计的工件)。
其他人是否有更明智的解释?
答案 0 :(得分:3)
如果在扩展切片表示法中没有这样的处理,您将无法区分l[1:]
和l[1::]
,并且您无法调用不同的特殊方法 - __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.c和data model description。