切片生成时给出的元组的元组

Tuple of tuple given on slice generation

我有这个代码:

class Foo(object):
     def __getitem__(self, *args):
        print len(args), type(args)
        print args

这给出 args 作为一个元组:

>>> x[1:]
1 <type 'tuple'>
(slice(1, None, None),)

但这给出了 args 作为元组的元组:

>>> x[1:,2:,3:]
1 <type 'tuple'>
((slice(1, None, None), slice(2, None, None), slice(3, None, None)),)

为什么会这样?我期待最后一个例子给我一个包含三个切片元素的元组。

__getitem__的函数签名是:

def __getitem__(self, key):
    # ... etc.

每当您对对象执行项目访问时,单个参数key将传递给__getitem__ (连同通常的隐含 self)。即使你这样写也是这样:

obj[a,b,c]

以上将导致单个元组 (a, b, c) 作为 key 参数传递给 __getitem__() – 它 而不是 导致传递三个参数 abc

因为单个 key 参数总是传递给 __getitem__argument unpacking 在格式错误的函数签名 __getitem__(self, *args) 中的效果是 args 将始终是一个仅包含一项(键)的元组。

在第一种情况下,由于您使用了切片语法,因此该键是一个切片:

 |<- slice object ->|
(slice(1, None, None),)
|<----- 1-tuple ----->|

在第二种情况下 – x[1:,2:,3:] – 您的 single 键是 3 个切片对象的元组,由于然后你的格式错误的函数签名被包裹在一个 1 元组中:

  |<- slice object ->|  |<- slice object ->|  |<- slice object ->|
 |<-------------------------- 3-tuple --------------------------->|
((slice(1, None, None), slice(2, None, None), slice(3, None, None)),)
|<--------------------------- 1-tuple ----------------------------->|

如果您将 __getitem__ 签名更改为常规 __getitem__(self, key) 形式,您将收到第二个示例所期望的三个切片对象的元组。