Python 2.6 / 3.0: Determining if a method is inherited

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Fuzzyman

    #1

    Python 2.6 / 3.0: Determining if a method is inherited

    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__.__se lf__
    <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__.__fu nc__
    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
    --
    Pedestrian accidents can happen in the blink of an eye, changing lives forever. When you're out for a stroll or crossing the street, an unexpected collision

  • MRAB

    #2
    Re: Python 2.6 / 3.0: Determining if a method is inherited

    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__.__sel f__
    <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__.__fun c__
    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__

    Comment

    • Aaron \Castironpi\ Brady

      #3
      Re: Python 2.6 / 3.0: Determining if a method is inherited

      On Oct 5, 7:13 pm, MRAB <goo...@mrabarn ett.plus.comwro te:
      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

      Comment

      • Fuzzyman

        #4
        Re: Python 2.6 / 3.0: Determining if a method is inherited

        On Oct 6, 1:13 am, MRAB <goo...@mrabarn ett.plus.comwro te:
        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__.__se lf__
        <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__.__fu nc__
        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
        --
        Pedestrian accidents can happen in the blink of an eye, changing lives forever. When you're out for a stroll or crossing the street, an unexpected collision

        Comment

        • Aaron \Castironpi\ Brady

          #5
          Re: Python 2.6 / 3.0: Determining if a method is inherited

          On Oct 6, 4:30 am, Fuzzyman <fuzzy...@gmail .comwrote:
          On Oct 6, 1:13 am, MRAB <goo...@mrabarn ett.plus.comwro te:
          >
          >
          >
          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__.__sel f__
          <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__.__fun c__
          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.ironpythoni naction.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.

          Comment

          • Fuzzyman

            #6
            Re: Python 2.6 / 3.0: Determining if a method is inherited

            On Oct 6, 7:01 pm, "Aaron \"Castironpi \" Brady" <castiro...@gma il.com>
            wrote:
            On Oct 6, 4:30 am, Fuzzyman <fuzzy...@gmail .comwrote:
            >
            >
            >
            On Oct 6, 1:13 am, MRAB <goo...@mrabarn ett.plus.comwro te:
            >
            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__.__se lf__
            <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__.__fu nc__
            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.ironpythoni naction.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
            --
            Pedestrian accidents can happen in the blink of an eye, changing lives forever. When you're out for a stroll or crossing the street, an unexpected collision

            Comment

            • Aaron \Castironpi\ Brady

              #7
              Re: Python 2.6 / 3.0: Determining if a method is inherited

              On Oct 6, 1:17 pm, Fuzzyman <fuzzy...@gmail .comwrote:
              On Oct 6, 7:01 pm, "Aaron \"Castironpi \" Brady" <castiro...@gma il.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.ironpythoni naction.com/
              Nope, I'm out of ideas, I'm afraid.

              Comment

              • Pekka Laukkanen

                #8
                Re: Python 2.6 / 3.0: Determining if a method is inherited

                2008/10/5 Fuzzyman <fuzzyman@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.ismetho d 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.ismet hod(C().__str__ )
                False
                >>inspect.ismet hod(D().__str__ )
                True
                >>inspect.ismet hod(E().__str__ )
                True
                >>>
                >>C().__str__.i m_class
                Traceback (most recent call last):
                File "<stdin>", line 1, in <module>
                AttributeError: 'method-wrapper' object has no attribute 'im_class'
                >>D().__str__.i m_class
                <class '__main__.D'>
                >>E().__str__.i m_class
                <class '__main__.E'>


                Cheers,
                .peke

                Comment

                • Pekka Laukkanen

                  #9
                  Re: Python 2.6 / 3.0: Determining if a method is inherited

                  2008/10/7 Pekka Laukkanen <peke@iki.fi> :
                  2008/10/5 Fuzzyman <fuzzyman@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.ismetho d 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.isme thod(C().__str_ _)
                  False
                  >>>inspect.isme thod(D().__str_ _)
                  True
                  >>>inspect.isme thod(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

                  Comment

                  Working...