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

Python 2.6 / 3.0: Determining if a method is inherited

P: n/a
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?

Michael Foord
--
http://www.ironpythoninaction.com/
Oct 5 '08 #1
Share this Question
Share on Google+
8 Replies


P: n/a
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__
Oct 6 '08 #2

P: n/a
On Oct 5, 7:13*pm, MRAB <goo...@mrabarnett.plus.comwrote:
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.
Hmmm... I can get this working with Python 2.6 with:

Methods are objects. How do you know if two references refer to the
same object? You use "is":

X.__lt__ is object.__lt__
That doesn't work for me.
>>class A( object ):
.... pass
....
>>class B( A ):
.... def __lt__( self, other ):
.... return self
....
>>a= A()
b= B()
B.__lt__ is object.__lt__
False
>>A.__lt__ is object.__lt__
False
>>>
Further, it's been noted before that

A().meth is not A().meth
Oct 6 '08 #3

P: n/a
On Oct 6, 1:13 am, MRAB <goo...@mrabarnett.plus.comwrote:
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/
Oct 6 '08 #4

P: n/a
On Oct 6, 4:30*am, Fuzzyman <fuzzy...@gmail.comwrote:
On Oct 6, 1:13 am, MRAB <goo...@mrabarnett.plus.comwrote:
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.
Oct 6 '08 #5

P: n/a
On Oct 6, 7:01*pm, "Aaron \"Castironpi\" Brady" <castiro...@gmail.com>
wrote:
On Oct 6, 4:30*am, Fuzzyman <fuzzy...@gmail.comwrote:
On Oct 6, 1:13 am, MRAB <goo...@mrabarnett.plus.comwrote:
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/
Oct 6 '08 #6

P: n/a
On Oct 6, 1:17*pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Oct 6, 7:01*pm, "Aaron \"Castironpi\" Brady" <castiro...@gmail.com>
wrote:
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/
Nope, I'm out of ideas, I'm afraid.
Oct 6 '08 #7

P: n/a
2008/10/5 Fuzzyman <fu******@gmail.com>:
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...)
I don't have Python 2.6 available, but if __lt__ on it works similarly
as __str__ on Python 2.5, you might be able to achieve this either
with inspect.ismethod or by checking methods' im_class attribute
directly:
>>class C(object):
.... pass
....
>>class D(object):
.... def __str__(self):
.... return ''
....
>>class E(D):
.... pass
....
>>import inspect
inspect.ismethod(C().__str__)
False
>>inspect.ismethod(D().__str__)
True
>>inspect.ismethod(E().__str__)
True
>>>
C().__str__.im_class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method-wrapper' object has no attribute 'im_class'
>>D().__str__.im_class
<class '__main__.D'>
>>E().__str__.im_class
<class '__main__.E'>
Cheers,
.peke
Oct 6 '08 #8

P: n/a
2008/10/7 Pekka Laukkanen <pe**@iki.fi>:
2008/10/5 Fuzzyman <fu******@gmail.com>:
>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...)

I don't have Python 2.6 available, but if __lt__ on it works similarly
as __str__ on Python 2.5, you might be able to achieve this either
with inspect.ismethod or by checking methods' im_class attribute
directly:
>>>class C(object):
... pass
...
>>>class D(object):
... def __str__(self):
... return ''
...
>>>class E(D):
... pass
...
>>>import inspect
inspect.ismethod(C().__str__)
False
>>>inspect.ismethod(D().__str__)
True
>>>inspect.ismethod(E().__str__)
True
>>>>
C().__str__.im_class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method-wrapper' object has no attribute 'im_class'
>>>D().__str__.im_class
<class '__main__.D'>
>>>E().__str__.im_class
<class '__main__.E'>
Ooops, didn't notice this was suggested already. One more attempt,
hopefully this is unique. =)
>>C().__str__.__objclass__
<type 'object'>
>>D().__str__.__objclass__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__objclass__'
>>'spam'.__str__.__objclass__
<type 'str'>

Someone who actually knows what __objclas__ does can probably comment
does this make any sense in your case.

Cheers,
.peke
Oct 6 '08 #9

This discussion thread is closed

Replies have been disabled for this discussion.