By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,275 Members | 1,745 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,275 IT Pros & Developers. It's quick & easy.

__getitem__ on new-style classes

P: n/a
What i'm trying to do is tie special methods of a "proxy" instance
to another instance:

def test1():
class Container:
def __init__( self, data ):
self.data = data
self.__getitem__ = self.data.__getitem__

data = range(10)
c = Container(data)
print "test1"
print c[3]

This works OK. But when I try the same thing on
new style classes:

def test2():
print "test2"
class Container(object):
def __init__( self, data ):
self.data = data
# self.__dict__["__getitem__"] = self.data.__getitem__
self.__setattr__( "__getitem__", self.data.__getitem__ )
data = range(10)
c = Container(data)
print
print c.__getitem__(3) # works OK
print c[3] # fails

I get a "TypeError: unindexable object". It
seems that c[] does not call __getitem__ in this case.

The plot thickens, however, when one tries the following:

def test3():
data = range(10)
c = type( "Container", (), { "__getitem__":data.__getitem__ } )()
print "test3"
print c[3]

Which works fine. However, if I need to resort to
such trickery, no-one here where i work will have any idea
what it does :)

Would anyone like to shed some light on what is going on here ?

bye,

Simon.

Jul 18 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
si***@arrowtheory.com wrote:
What i'm trying to do is tie special methods of a "proxy" instance
to another instance: .... new style classes:

def test2():
print "test2"
class Container(object):
def __init__( self, data ):
self.data = data
# self.__dict__["__getitem__"] = self.data.__getitem__
self.__setattr__( "__getitem__", self.data.__getitem__ )
data = range(10)
c = Container(data)
print
print c.__getitem__(3) # works OK
print c[3] # fails

I get a "TypeError: unindexable object". It
seems that c[] does not call __getitem__ in this case. because __getitem__ is looked up in the class, not the instance dictionary
The plot thickens, however, when one tries the following:

def test3():
data = range(10)
c = type( "Container", (), { "__getitem__":data.__getitem__ } )()
print "test3"
print c[3]


Here you've created an entry in the class dictionary, just like writing
data = range(10)
class Container(object):
__getitem__ = data.__getitem__

but, this probably doesn't help you much if you want the method to delegate to
an attribute of the instance, since the instance is unavailable at class
definition time

So, one solution, is to use create a delegating descriptor, like so:

class Delegate(object):
def __init__(self, attrname):
self.attrname = attrname
def __get__(self, obj, cls):
if isinstance(obj, cls):
# Note that the attribute is looked up on obj._data
return getattr(obj._data, self.attrname)
else:
return self

class Example(object):
__getitem__ = Delegate("__getitem__")

def __init__(self, delegate):
self._data = delegate
e = Example(range(10))
e[3]

3
Michael
Jul 18 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.