What method does slice notation call?

R

Robert Brewer

class A(types.DictType):
.... def __getitem__(self, key):
.... return types.DictType.__getitem__(self, key)
....
a = A()
a[0] = 3
a.__getitem__ = lambda x: "w00t"
a.__getitem__(0) 'w00t'
a {0: 3}
a[0]
3

Can anyone tell me why a[0] doesn't return "w00t", like I thought it
would? What method is a[0] calling? Is there a way to override it?


Robert Brewer
MIS
Amor Ministries
(e-mail address removed)
 
P

Peter Otten

Robert said:
... def __getitem__(self, key):
... return types.DictType.__getitem__(self, key)
...
a = A()
a[0] = 3
a.__getitem__ = lambda x: "w00t"
a.__getitem__(0) 'w00t'
a {0: 3}
a[0]
3

Can anyone tell me why a[0] doesn't return "w00t", like I thought it
would? What method is a[0] calling? Is there a way to override it?

The special methods are somewhat reluctant when you try to override them on
the instance level. Here are two ways using brute force.
(There are probably more elegant ways that involve metaclasses...)

Peter

<code>
import types

# implement __getitem__() in terms of a "normal" method
# that can be overridden on a per instance basis
class A(types.DictType):
def getitem(self, key):
return types.DictType.__getitem__(self, key)
def __getitem__(self, key):
return self.getitem(key)

a = A()
a.getitem = lambda key: "if you must"

print a["dummy"]

# just subclassing...
class B(A):
__getitem__ = lambda self, key: "there you are"

b = B()
print b["dummy"]
</code>
 
A

Alex Martelli

Robert said:
... def __getitem__(self, key):
... return types.DictType.__getitem__(self, key)
...
a = A()
a[0] = 3
a.__getitem__ = lambda x: "w00t"
a.__getitem__(0) 'w00t'
a {0: 3}
a[0]
3

Can anyone tell me why a[0] doesn't return "w00t", like I thought it
would? What method is a[0] calling? Is there a way to override it?

For all except "classic classes" (which have to do lots of hacking
behind the scenes for backwards compatibility, sigh), a[0] means
roughly the equivalent of:

getattr(type(a), '__getitem__')(a, 0)

so, if you want to have a[0] invoke something different, you must
change type(a) accordingly, e.g.:

def changeindexing(a, newgetitem):
class x(type(a)):
__getitem__ = newgetitem
a.__class__ = x

so, for example:

def changeindexing(a, newgetitem):
class x(type(a)):
__getitem__ = newgetitem
a.__class__ = x

class A(dict):
def __getitem__(self, key):
return dict.__getitem__(self, key)

a = A()
a[0] = 3
a.__getitem__ = lambda x: "w00t"
print a.__getitem__(0)
print a
print a[0]

changeindexing(a, lambda self, x: 'blaap')

print a.__getitem__(0)
print a
print a[0]

prints:

w00t
{0: 3}
3
w00t
{0: 3}
blaap


Note that the function you pass to changeindexing does need a 'self', just
like any other method. If you don't want that, you can use a staticmethod,
of course (but then the function won't have access to the specific instance
it's being called on).


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top