Is this a super bug?
Bjorn Pettersen
BPettersen at NAREX.com
Sun Apr 20 00:07:30 EDT 2003
> From: Terry Reedy [mailto:tjreedy at udel.edu]
>
> "Bjorn Pettersen" <BPettersen at NAREX.com> wrote in message
>
> >>> class ff(str):
> ... def foo(self):
[...]
> ... print 'super(ff, self)[0]', super(ff, self)[0]
> ...
> >>> f = ff('asdf')
> >>> f.foo()
> super(ff, self)[0]
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "<stdin>", line 5, in foo
> TypeError: unsubscriptable object
> ----------
> I suspect that printing type(super(ff,self)) might answer your
> question.
I'm afraid not :-) I allready did that, and from what I can tell, this
is the sequence that "should" happen:
1 super(ff, f)[0] # f == self
2 superinst(type:<class ff>, obj:f)[0]
3 si.__getitem__(0)
4 si.__getattr__('__getitem__')
5 .. return str.__dict__['__getitem__'].__get__(f)
6 boundmethod(str.__getitem__, f)
7 bmeth(0)
8 'a'
well, the transition from 3 to 4 doesn't happen which surprised me a
little. What surprised me more was that I couldn't get __getattribute__
to be called either (neither in the class or its metaclass... I've only
got 2.3a2, and I read a note about this not working before a4. Is this
what is happening? If not, the only other reason I could see would be
from the refMan 5.3.2, "The primary must evaluate to an object of a
sequence or mapping type." If that is the case, then I still think it's
a super bug, i.e. there is no reason super should assume that it's not
"going to be" a sequence, in fact the direct superclass of ff _is_ a
sequence. To fix it simply add:
def __getitem__(self, v):
m = self.__getattr__('__getitem__')
return m(v)
to the definition of super. This will change the exception to
AttributeError if a superclass isn't a sequence. To keep the current
semantics, add the lookup to only instances that are sequence proxies
(example below, refactor between __getattr__ as desired...)
-- bjorn
class Super(object):
def __init__(self, type, obj=None):
self.__type__ = type
self.__obj__ = obj
if isinstance(self.__obj__, self.__type__):
starttype = self.__obj__.__class__
else:
starttype = self.__obj__
mro = iter(starttype.__mro__)
for cls in mro:
if cls is self.__type__:
break
for cls in mro:
if '__getitem__' in cls.__dict__:
def getitem(v):
m = self.__getattr__('__getitem__')
return m(v)
self.__possibleGetitem = getitem
break
def __possibleGetitem(self, v):
raise TypeError("unindexable object")
def __getitem__(self, v):
return self.__possibleGetitem(v)
More information about the Python-list
mailing list