Python 2.6 / 3.0: Determining if a method is inherited

Fuzzyman fuzzyman at gmail.com
Mon Oct 6 14:17:01 EDT 2008


On Oct 6, 7:01 pm, "Aaron \"Castironpi\" Brady" <castiro... at gmail.com>
wrote:
> On Oct 6, 4:30 am, Fuzzyman <fuzzy... at gmail.com> wrote:
>
>
>
> > On Oct 6, 1:13 am, MRAB <goo... at mrabarnett.plus.com> wrote:
>
> > > Fuzzyman wrote:
> > > > Hello all,
>
> > > > I may well be being dumb (it has happened before), but I'm struggling
> > > > to fix some code breakage with Python 2.6.
>
> > > > I have some code that looks for the '__lt__' method on a class:
>
> > > > if hasattr(clr, '__lt__'):
>
> > > > However - in Python 2.6 object has grown a default implementation of
> > > > '__lt__', so this test always returns True.
>
> > > > >>> class X(object): pass
> > > > ...
> > > > >>> X.__lt__
> > > > <method-wrapper '__lt__' of type object at 0xa15cf0>
> > > > >>> X.__lt__ == object.__lt__
> > > > False
>
> > > > So how do I tell if the X.__lt__ is inherited from object? I can look
> > > > in the '__dict__' of the class - but that doesn't tell me if X
> > > > inherits '__lt__' from a base class other than object. (Looking inside
> > > > the method wrapper repr with a regex is not an acceptable answer...)
>
> > > > Some things I have tried:
>
> > > > >>> X.__lt__.__self__
> > > > <class '__main__.X'>
> > > > >>> dir(X.__lt__)
> > > > ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',
> > > > '__format__', '__getattribute__', '__hash__', '__init__', '__name__',
> > > > '__new__', '__objclass__', '__reduce__', '__reduce_ex__', '__repr__',
> > > > '__self__', '__setattr__', '__sizeof__', '__str__',
> > > > '__subclasshook__']
> > > > >>> X.__lt__.__func__
> > > > Traceback (most recent call last):
> > > >   File "<stdin>", line 1, in <module>
> > > > AttributeError: 'method-wrapper' object has no attribute '__func__'
>
> > > > Hmmm... I can get this working with Python 2.6 with:
>
> > > > if '__lt__' in dir(cls):
>
> > > > The default implementation of '__lt__' doesn't appear in the dir of
> > > > classes. However this fails with Python 3 where the default
> > > > implementation *does* appear in the output of 'dir'. Any suggestions?
>
> > > Methods are objects. How do you know if two references refer to the
> > > same object? You use "is":
>
> > > X.__lt__ is object.__lt__
>
> > Didn't you see that even an equality test fails - so they are not the
> > same (that being the problem)...
>
> > They are unbound method objects - in Python 3 the unbound method has
> > gone away, so the problem is with Python 2.6.
>
> > Michael
> > --http://www.ironpythoninaction.com/
>
> Not tested extensively.
>
> class NoLTException( Exception ): pass
>
> class NoLT( object ):
>     def __lt__( self, other ):
>             raise NoLTException()
>
> class A( NoLT ):
>     pass
>
> class B( A ):
>     def __lt__( self, other ):
>             return self
>
> def test_lt( obj ):
>     try:
>             obj.__lt__( None )
>     except NoLTException:
>             return False
>     except:
>             pass
>     return True
>
>
>
> >>> a= A()
> >>> b= B()
> >>> test_lt( a )
> False
> >>> test_lt( b )
> True
>
> This method won't work for arbitrary classes, only ones that you
> control, that inherit from 'NoLT'.  The 'test_lt' function works by
> trying to call '__lt__' on its argument.  The parameter to it doesn't
> matter because of what happens next.  If '__lt__' raises a
> NoLTException, you know it was inherited from NoLT.  Otherwise, even
> if another exception occurs, the object you know has '__lt__'.
>
> It's a very object oriented solution.  Essentially you're inheriting
> all the classes that you want to fail, from a class that does.

But not a very good solution to the problem...

The specific problem is to determine if an arbitrary class implements
a specified comparison method. The general problem (that gives rise to
the specific problem) is to write a class decorator that can implement
all comparison methods from a class that implements only one.

See: http://code.activestate.com/recipes/576529/

Michael
--
http://www.ironpythoninaction.com/



More information about the Python-list mailing list