0

我有这个代码:

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)),)

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

4

1 回答 1

1

__getitem__的函数签名是:

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

每当您对对象执行项目访问时,都会将单个参数key传递给__getitem__(与通常的impled 一起self)。即使您编写如下内容也是如此:

obj[a,b,c]

以上将导致单个元组(a, b, c)作为key参数传递给__getitem__()- 它不会导致三个参数a,bc被传递。

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

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

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

在第二种情况下——x[1:,2:,3:]你的单个键是 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)形式,您将收到您期望在第二个示例中使用的三个切片对象的元组。

于 2017-12-10T17:59:44.433 回答