Python 2.6: Determining if a method is inherited

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

    #1

    Python 2.6: 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__'

    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

  • Valentino Volonghi aka Dialtone

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

    Fuzzyman <fuzzyman@gmail .comwrote:
    So how do I tell if the X.__lt__ is inherited from object? I can look
    I don't have python 2.6 installed so I can't try but what I think could
    work is:
    >>class Foo(object):
    .... def hello(self):
    .... pass
    ....
    >>class Bla(Foo):
    .... def hello(self):
    .... pass
    ....
    >>class Baz(Foo):
    .... pass
    ....
    >>Baz.hello.im_ func
    <function hello at 0x2b1630>
    >>Bla.hello.im_ func
    <function hello at 0x2b1670>
    >>Foo.hello.im_ func
    <function hello at 0x2b1630>
    >>Foo.hello.im_ func is Baz.hello.im_fu nc
    True
    >>Foo.hello.im_ func is Bla.hello.im_fu nc
    False

    Which to me also makes sense. If it's inherited I expect it to be the
    very same function object of one of the bases (which you can get with
    inspect.getmro( Clazz)). On the other end if you override it it's not the
    same function object so it won't return True when applied to 'is'.

    HTH

    --
    Valentino Volonghi aka Dialtone
    http://stacktrace.it -- Aperiodico di resistenza informatica
    Blog: http://www.twisted.it/
    Public Beta: http://www.adroll.com/

    Comment

    • Aaron \Castironpi\ Brady

      #3
      Re: Python 2.6: 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...)
      They're of different types. I'm not sure how much you could use that,
      or how reliable it is.
      >>class A( object ):
      .... pass
      ....
      >>class B( object ):
      .... def __lt__( self, other ):
      .... pass
      ....
      >>hasattr( A, '__lt__' )
      True
      >>hasattr( B, '__lt__' )
      True
      >>A.__lt__
      <method-wrapper '__lt__' of type object at 0x00B81D48>
      >>B.__lt__
      <unbound method B.__lt__>
      >>>

      Comment

      • Fuzzyman

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

        On Oct 5, 8:15 pm, dialUAZ###UZ#$A At...@gWARAmail .com (Valentino
        Volonghi aka Dialtone) wrote:
        Fuzzyman <fuzzy...@gmail .comwrote:
        So how do I tell if the X.__lt__ is inherited from object? I can look
        >
        I don't have python 2.6 installed so I can't try but what I think could
        work is:
        >
        >class Foo(object):
        >
        ...     def hello(self):
        ...         pass
        ...>>class Bla(Foo):
        >
        ...     def hello(self):
        ...         pass
        ...>>class Baz(Foo):
        >
        ...     pass
        ...>>Baz.hello. im_func
        >
        <function hello at 0x2b1630>>>Bla. hello.im_func
        >
        <function hello at 0x2b1670>>>Foo. hello.im_func
        >
        <function hello at 0x2b1630>>>Foo. hello.im_func is Baz.hello.im_fu nc
        True
        >Foo.hello.im_f unc is Bla.hello.im_fu nc
        >
        False
        >

        Nope:

        Python 2.6 (trunk:66714:66 715M, Oct 1 2008, 18:36:04)
        [GCC 4.0.1 (Apple Computer, Inc. build 5370)] on darwin
        Type "help", "copyright" , "credits" or "license" for more information.
        >>class X(object): pass
        ....
        >>X.__lt__.im_f unc
        Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        AttributeError: 'method-wrapper' object has no attribute 'im_func'
        >>>
        What I went with in the end:

        import sys as _sys

        if _sys.version_in fo[0] == 3:
        def _has_method(cls , name):
        for B in cls.__mro__:
        if B is object:
        continue
        if name in B.__dict__:
        return True
        return False
        else:
        def _has_method(cls , name):
        for B in cls.mro():
        if B is object:
        continue
        if name in B.__dict__:
        return True
        return False

        See this page for why I needed it:

        http://www.voidspace.org.uk/python/w...04.shtml#e1018

        Michael
        Which to me also makes sense. If it's inherited I expect it to be the
        very same function object of one of the bases (which you can get with
        inspect.getmro( Clazz)). On the other end if you override it it's not the
        same function object so it won't return True when applied to 'is'.
        >
        HTH
        >
        --
        Valentino Volonghi aka Dialtonehttp://stacktrace.it-- Aperiodico di resistenza informatica
        Blog:http://www.twisted.it/
        Public Beta:http://www.adroll.com/

        Comment

        • Terry Reedy

          #5
          Re: Python 2.6: 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
          In 3.0, the test returns true because function attributes only get
          wrapped when bound. In the meanwhile, " 'object' in repr(X.__lt__)"
          should do it for you.

          tjr

          Comment

          • Christian Heimes

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

            Terry Reedy wrote:
            In 3.0, the test returns true because function attributes only get
            wrapped when bound. In the meanwhile, " 'object' in repr(X.__lt__)"
            should do it for you.
            This session should give you some hints how to archive your goal :)
            Have fun!
            >>import types
            >>class A(object):
            .... def __lt__(self):
            .... pass
            ....
            >>isinstance(A. __lt__, types.MethodTyp e)
            True
            >>isinstance(A. __gt__, types.MethodTyp e)
            False
            >>type(A.__lt__ )
            <type 'instancemethod '>
            >>type(A.__gt__ )
            <type 'method-wrapper'>
            >>type(A.__str_ _)
            <type 'wrapper_descri ptor'>
            >>type(A.__new_ _)
            <type 'builtin_functi on_or_method'>
            >>A.__lt__.im_f unc
            <function __lt__ at 0x7f03f9298500>
            >>A.__lt__.im_f unc == A.__lt__.im_fun c
            True
            >>A.__gt__.im_f unc
            Traceback (most recent call last):
            File "<stdin>", line 1, in <module>
            AttributeError: 'method-wrapper' object has no attribute 'im_func'

            Comment

            • Fuzzyman

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

              On Oct 5, 11:54 pm, Terry Reedy <tjre...@udel.e duwrote:
              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
              >
              In 3.0, the test returns true because function attributes only get
              wrapped when bound. In the meanwhile, " 'object' in repr(X.__lt__)"
              should do it for you.
              >

              So long as its never used on a class with 'object' in the name.
              Doesn't sound like a particularly *good* solution to me. :-)

              Michael
              tjr
              --
              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

              • Fuzzyman

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

                On Oct 6, 7:16 am, Christian Heimes <li...@cheimes. dewrote:
                Terry Reedy wrote:
                In 3.0, the test returns true because function attributes only get
                wrapped when bound. In the meanwhile, " 'object' in repr(X.__lt__)"
                should do it for you.
                >
                This session should give you some hints how to archive your goal :)
                Have fun!
                >
                >>import types
                >>class A(object):
                ... def __lt__(self):
                ... pass
                ...
                >>isinstance(A. __lt__, types.MethodTyp e)
                True
                >>isinstance(A. __gt__, types.MethodTyp e)
                False
                >
                >>type(A.__lt__ )
                <type 'instancemethod '>
                >>type(A.__gt__ )
                <type 'method-wrapper'>
                >>type(A.__str_ _)
                <type 'wrapper_descri ptor'>
                >>type(A.__new_ _)
                <type 'builtin_functi on_or_method'>
                >
                >>A.__lt__.im_f unc
                <function __lt__ at 0x7f03f9298500>
                >>A.__lt__.im_f unc == A.__lt__.im_fun c
                True
                >>A.__gt__.im_f unc
                Traceback (most recent call last):
                File "<stdin>", line 1, in <module>
                AttributeError: 'method-wrapper' object has no attribute 'im_func'
                However - I need to detect whether a method is inherited from
                *object*. All those differences you have shown behave identically if
                the class inherits from 'int'.

                I am trying to detect explicit implementation of comparison methods -
                so there is a big difference between inheriting from int and
                inheriting from object (meaningful comparison methods existing on one
                and not the other).

                What I went for in the end:

                import sys as _sys

                if _sys.version_in fo[0] == 3:
                def _has_method(cls , name):
                for B in cls.__mro__:
                if B is object:
                continue
                if name in B.__dict__:
                return True
                return False
                else:
                def _has_method(cls , name):
                for B in cls.mro():
                if B is object:
                continue
                if name in B.__dict__:
                return True
                return False

                See this page for why I needed it:

                http://www.voidspace.org.uk/python/w...04.shtml#e1018

                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

                • Terry Reedy

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

                  Fuzzyman wrote:
                  On Oct 5, 11:54 pm, Terry Reedy <tjre...@udel.e duwrote:
                  >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
                  >In 3.0, the test returns true because function attributes only get
                  >wrapped when bound. In the meanwhile, " 'object' in repr(X.__lt__)"
                  >should do it for you.
                  So long as its never used on a class with 'object' in the name.
                  Doesn't sound like a particularly *good* solution to me. :-)
                  From what you posted, 'type object at' should work.

                  Comment

                  • Fuzzyman

                    #10
                    Re: Python 2.6: Determining if a method is inherited

                    On Oct 6, 7:02 pm, Terry Reedy <tjre...@udel.e duwrote:
                    Fuzzyman wrote:
                    On Oct 5, 11:54 pm, Terry Reedy <tjre...@udel.e duwrote:
                    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
                    In 3.0, the test returns true because function attributes only get
                    wrapped when bound.  In the meanwhile, " 'object' in repr(X.__lt__)"
                    should do it for you.
                    So long as its never used on a class with 'object' in the name.
                    Doesn't sound like a particularly *good* solution to me. :-)
                    >
                     From what you posted, 'type object at' should work.
                    It's still a hack...

                    Comment

                    • Terry Reedy

                      #11
                      Re: Python 2.6: Determining if a method is inherited

                      Fuzzyman wrote:
                      On Oct 6, 7:02 pm, Terry Reedy <tjre...@udel.e duwrote:
                      >fuzzyman wrote:
                      >>Doesn't sound like a particularly *good* solution to me. :-)
                      > From what you posted, 'type object at' should work.
                      >
                      It's still a hack...
                      I am sorry if I offended you by pointing out to you a quick and dirty
                      solution that would solve your problem immediately.


                      Comment

                      • Fuzzyman

                        #12
                        Re: Python 2.6: Determining if a method is inherited

                        On Oct 7, 2:29 am, Terry Reedy <tjre...@udel.e duwrote:
                        Fuzzyman wrote:
                        On Oct 6, 7:02 pm, Terry Reedy <tjre...@udel.e duwrote:
                        fuzzyman wrote:
                        >Doesn't sound like a particularly *good* solution to me. :-)
                         From what you posted, 'type object at' should work.
                        >
                        It's still a hack...
                        >
                        I am sorry if I offended you by pointing out to you a quick and dirty
                        solution that would solve your problem immediately.
                        Your smiley parsing is obviously broken.

                        Michael

                        Comment

                        Working...