rub*_*gly 5 python abstract-syntax-tree
这可以通过示例得到最好的说明(假设所有示例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)
Run Code Online (Sandbox Code Playgroud)
因此,正如我们所看到的,l[1:10]结果是一个AST节点,其切片有两个子节点 - lower并且upper都设置为数字文字 - 并且是一个空的第三step个子节点.但是[1:10:],我们认为它们是相同的,将其切片的step子项设置为None文字表达式(Name(id='None', ctx=Load())).
好的,我想.也许Python的对待l[1:10:],并l[1:10]为完全不同类型的表达式.Python表达式引用(链接)当然似乎表明了这一点; 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)
Run Code Online (Sandbox Code Playgroud)
此外,经过进一步检查,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)
Run Code Online (Sandbox Code Playgroud)
所以这是我的结论:AST始终把step参数特殊出于某种原因,并unrelatedly的SliceAST节点代表长片(我猜所以不必是两个不同的基Slice类- ShortSlice和LongSlice-虽然我认为因此,单项扩展切片可以表示为正常Slice节点,并且由于某种原因这样做.允许将None参数解释为默认值似乎是错误的,但我理解这是一个有目的的设计决策; 在None文字插入和治疗长片的Slice节点似乎只是有点像事故(或旧的设计的假象).
还有其他人有更明智的解释吗?
如果没有扩展切片符号中的这种处理,您将无法区分 和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)'
>>>
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅ast.c 的 python2.7 源代码和数据模型描述。