Python的扩展切片表示法的形式语法?

时间:2017-11-06 09:58:17

标签: python syntax slice

例如,Numpy允许多维切片:

a[:, 0, 7:9]

这提出了一个问题:还有什么可能? (想象一下可能性!)

根据this answer和一些实验(见下文),如果有逗号,Python会构建一个对象元组,其中一些可能是切片对象,并传递它(如key)到__getitem__(self, key)的{​​{1}}。

documentation for __getitem__(..)没有指定此行为。有没有我错过的官方文件?特别是,这种语法如何向后兼容? (在网上搜索" python扩展切片表示法"给出"What's new in Python 2.3",但是没有提到它。)

实验

a

首先,Python发现可以识别多切片的东西:

>>> class Test(object):
...     def __getitem__(self, x):
...         print repr(x)


>>> t = Test()

一些不允许的事情(SyntaxError):

>>> t[1]
1

>>> t['a':,]
(slice('a', None, None),)

>>> t['a':7:('b','c'),]
(slice('a', 7, ('b', 'c')),)

# Seems like it can be arbitrary objects?
>>> t[(t,t):[4,5]]
slice((<__main__.Test object at 0x07D04950>, <__main__.Test object at 0x07D04950>), [4, 5], None)

>>> t[::]
slice(None, None, None)

>>> t[:]
slice(None, None, None)

>>> t[::,1,::,::,:,:,:]
(slice(None, None, None), 1, slice(None, None, None), slice(None, None, None), slice(None, None, None),  slice(None, None, None), slice(None, None, None))

>>> t[...]
Ellipsis

>>> t[... , ...]
(Ellipsis, Ellipsis)

>>> t[  .   .      .    ]
Ellipsis

1 个答案:

答案 0 :(得分:5)

任何是可能的,只要它是有效的Python表达式。由[...]之间的表达式生成的对象将传递给__getitem__方法。那就是它。

逗号生成一个元组,:冒号在表达式中生成slice()个对象。除此之外,使用你想要的任何东西。

这是因为语法允许在符号中使用任何expression_list 。请参阅reference documentation

subscription ::=  primary "[" expression_list "]"

Slicings section

中进一步指定切片
slicing      ::=  primary "[" slice_list "]"
slice_list   ::=  slice_item ("," slice_item)* [","]
slice_item   ::=  expression | proper_slice
proper_slice ::=  [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound  ::=  expression
upper_bound  ::=  expression
stride       ::=  expression

因此允许任意expression:触发proper_slice语法规则。

请注意,lower_boundupper_boundstride表达式结果用于构造slice()对象,该对象只能处理整数值 。任何无法转换为整数的内容都会导致TypeError被提升。这与语法错误不同; t[1:...]在语法上很好,但是...不能转换为整数,因此会得到运行时TypeError异常。使用非整数切片值的两个示例在Python 2.4及更低版本上是不可能的。

您的实际语法错误都源于无效表达式。除了: proper_slice符号之外,如果您不能将[...]之间的部分放在作业的右侧,则无法在作业中使用它切片。

例如,;只能用于在单个逻辑行上放置多个simple statements。语句可以包含表达式,但表达式永远不能包含语句,不包括表达式中的;(9:5),不是有效的表达式(在Python中没有其他地方可以在括号中使用:parenth_form rule不允许任何此类选项。)

Python 2 grammar for slicings稍微复杂一点,...是语法中的特定符号,你实际上不能使用切片之外的...(在Python 3你可以在表达式有效的任何地方使用...,这就是为什么t[(...)]是Python 2中的语法错误而不是Python 3中的语法错误。