这可以通过示例进行最好的说明(所有示例都假设导入了ast;请注意,我使用的是Python2.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都设置为数字字面值--以及一个空的第三个step子节点。但是,我们认为完全相同的[1:10:]将其切片的step子级设置为None文字表达式(Name(id='None', ctx=Load()))。
好吧,我想。也许Python将l[1:10:]和l[1:10]视为完全不同类型的表达式。l[1:10]表达式参考(link)显然表明了这一点;Python是一个简单的切片,但l[1:10:]是一个扩展切片(只有一个切片项)。
但是,即使在扩展切片的上下文中,步骤参数也是特殊对待的。如果我们尝试忽略带有一个切片项的扩展切片中的上界或下界,我们最终只会得到空子对象:
# 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基类-ShortSlice和LongSlice-though,我认为这会更好),因此单项扩展切片可以表示为普通的Slice节点,并且出于某种原因这样做。在我看来,允许将None参数解释为默认值似乎是错误的,但我理解这是一个有目的的设计决策;None文字插入并将长片段视为Slice节点看起来有点像是意外(或旧设计的工件)。
还有没有人有更明智的解释?
发布于 2011-12-09 21:50:46
如果在扩展切片表示法中没有这样的处理,您将无法区分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。
https://stackoverflow.com/questions/8440248
复制相似问题