I have this code:
class Foo(object):
def __getitem__(self, *args):
print len(args), type(args)
print args
This gives args
as a tuple:
>>> x[1:]
1 <type 'tuple'>
(slice(1, None, None),)
But this gives args as a tuple of tuples:
>>> x[1:,2:,3:]
1 <type 'tuple'>
((slice(1, None, None), slice(2, None, None), slice(3, None, None)),)
Why so? I was expecting the last example to give me a tuple with three slice elements.
__getitem__
's function signature is:
def __getitem__(self, key):
# ... etc.
Whenever you perform item access on an object, a single argument key
is passed to __getitem__
(alongside the usual impled self
). This is the case even if you write something like this:
obj[a,b,c]
The above will cause the single tuple (a, b, c)
to be passed as the key
argument to __getitem__()
– it does not cause three arguments a
, b
and c
to be passed.
Because a single key
argument is always passed to __getitem__
, the effect of argument unpacking in your malformed function signature __getitem__(self, *args)
is that args
will always be a tuple containing exactly one item (the key).
In the first case, since you used slice syntax, that key is a slice:
|<- slice object ->|
(slice(1, None, None),)
|<----- 1-tuple ----->|
In the second case – x[1:,2:,3:]
– your single key is a tuple of 3 slice objects, which due to your malformed function signature is then wrapped in a 1-tuple:
|<- slice object ->| |<- slice object ->| |<- slice object ->|
|<-------------------------- 3-tuple --------------------------->|
((slice(1, None, None), slice(2, None, None), slice(3, None, None)),)
|<--------------------------- 1-tuple ----------------------------->|
If you change your __getitem__
signature to the conventional __getitem__(self, key)
form, you'll receive the tuple of three slice objects that you expect for your second example.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.