Overloading operators

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

    Overloading operators

    Hi,
    in a project I'm overloading a lot of comparison and arithmetic
    operators to make them working with more complex classes that I
    defined.

    Sometimes I need a different behavior of the operator depending on the
    argument. For example, if I compare a object with an int, I get a
    result, but if I compare the same object with a string, or another
    object, I get another result.

    What is the best way to do this? Shall I use a lot of "if...elif"
    statements inside the overloaded operator? Or is there a more pythonic
    and dynamic way?
  • Aaron \Castironpi\ Brady

    #2
    Re: Overloading operators

    On Oct 15, 7:34 am, Mr.SpOOn <mr.spoo...@gma il.comwrote:
    Hi,
    in a project I'm overloading a lot of comparison and arithmetic
    operators to make them working with more complex classes that I
    defined.
    >
    Sometimes I need a different behavior of the operator depending on the
    argument. For example, if I compare a object with an int, I get a
    result, but if I compare the same object with a string, or another
    object, I get another result.
    >
    What is the best way to do this? Shall I use a lot of "if...elif"
    statements inside the overloaded operator? Or is there a more pythonic
    and dynamic way?
    Multimethods do the thing you're looking for. Google: 'python
    multimethods' gives:



    by van Rossum. Some examples:

    from mm import multimethod

    @multimethod(in t, int)
    def foo(a, b):
    ...code for two ints...

    @multimethod(fl oat, float):
    def foo(a, b):
    ...code for two floats..

    It is especially good if you're using inheritance. You could also
    collect the names of the types, and call a function by name:

    (untested)
    fname= a.__class__.__n ame__+ '_'+ b.__class__.__n ame__
    or
    fname= re.sub( '[^a-Za-z0-9]+', '', str( type( a ) ) ) + same
    type( b )
    ffunc= getattr( namespace, fname )

    or build a dictionary.

    (untested)
    f= {}
    f[ int, int ]= compA
    f[ int, str ]= compB
    ....
    ffunc= f[ type( a ), type( b ) ]

    What's your favorite?

    Comment

    • Robert Lehmann

      #3
      Re: Overloading operators

      On Wed, 15 Oct 2008 14:34:14 +0200, Mr.SpOOn wrote:
      Hi,
      in a project I'm overloading a lot of comparison and arithmetic
      operators to make them working with more complex classes that I defined.
      >
      Sometimes I need a different behavior of the operator depending on the
      argument. For example, if I compare a object with an int, I get a
      result, but if I compare the same object with a string, or another
      object, I get another result.
      >
      What is the best way to do this? Shall I use a lot of "if...elif"
      statements inside the overloaded operator? Or is there a more pythonic
      and dynamic way?
      If all your comparison methods do more or less the same (even if not but
      then it will be kinda less useful for complex operations) you could use
      dictionary-based dispatching. You would basically construct a dictionary
      of type->comparator mappings, like this::

      dispatch = {
      int: int_compare_fun ction,
      str: str_compare_fun ction,
      }

      And dispatch according to the other object's type::

      def __cmp__(self, other):
      return dispatch[type(other)]()

      (Assuming good faith and just throwing a `KeyError` for unimplemented
      types.)

      If you just needed to dispatch on a special attribute depending on the
      other object's type, you could redesign the dispatch dictionary to be a
      type->attribute mapping and go somewhere along this way::

      dispatch = {
      int: 'value',
      str: 'name',
      }
      def __cmp__(self, other):
      return cmp(getattr(sel f, dispatch[type(other)]), other)

      HTH,

      --
      Robert "Stargaming " Lehmann

      Comment

      • Aaron \Castironpi\ Brady

        #4
        Re: Overloading operators

        On Oct 15, 7:34 am, Mr.SpOOn <mr.spoo...@gma il.comwrote:
        Hi,
        in a project I'm overloading a lot of comparison and arithmetic
        operators to make them working with more complex classes that I
        defined.
        >
        Sometimes I need a different behavior of the operator depending on the
        argument. For example, if I compare a object with an int, I get a
        result, but if I compare the same object with a string, or another
        object, I get another result.
        >
        What is the best way to do this? Shall I use a lot of "if...elif"
        statements inside the overloaded operator? Or is there a more pythonic
        and dynamic way?
        Off topic.
        For the record, the solution in C is pretty bad without using true
        overloading. There's no literal hash, and you have to carry your
        types with your variables, possibly using a union. But if so, you can
        use an enum and an array. This owes to the uniformity of function
        signatures of the comparitors you're using.

        (uncompiled)

        typedef ( int comparitor_t* )( void* ob1, void* ob2 );
        comparitor_t comparitors[]= { compare_ints, compare_strs /*,
        others*/ };
        enum comparison_type s {
        ints= 0,
        strs= 1
        };
        struct variant {
        comparison_type s type;
        union {
        int i;
        str s;
        };
        };

        int compare( variant& a, variant& b ) {
        assert( a.type== b.type );
        return comparitors[ a.type ]( a, b );
        }

        'compare' knows how to retrieve its members from the union. The 'int'
        comparitor accesses the 'i' field, &c. Your compiler needs to know
        that enums are ints or that they can be indices into an array.

        For BASIC and even VisualBasic up to version 6, you have no choice but
        use a switch statement. The addressof operator won't help since
        you're not calling DLL entry points. VisualBasic.NET claims to
        overload functions. But C++ and VB can both employ the Visitor
        pattern "double-dispatch". It would be good practice to use Visitor
        to keep your options open across more languages, except that it's kind
        of trivial in Python, oddly enough. Good middle ground, I guess.

        Comment

        • Kay Schluehr

          #5
          Re: Overloading operators

          On 15 Okt., 14:34, Mr.SpOOn <mr.spoo...@gma il.comwrote:
          Hi,
          in a project I'm overloading a lot of comparison and arithmetic
          operators to make them working with more complex classes that I
          defined.
          >
          Sometimes I need a different behavior of the operator depending on the
          argument. For example, if I compare a object with an int, I get a
          result, but if I compare the same object with a string, or another
          object, I get another result.
          >
          What is the best way to do this? Shall I use a lot of "if...elif"
          statements inside the overloaded operator? Or is there a more pythonic
          and dynamic way?
          I can't see anything wrong about it. Sometimes I try to avoid
          isinstance() though because it is a rather slow operation. If the
          majority of operations is single-typed one can also use a try-stmt:

          def __add__(self, other):
          try:
          return self._val + other
          except TypeError:
          return self.__add__(So meWrapper(other ))

          and compare performance using a profiler. Notice that also

          if type(obj) == T:
          BLOCK

          is much faster than isinstance() but it's not OO-ish and very rigid.

          Comment

          • Mr.SpOOn

            #6
            Re: Overloading operators

            Thanks for the suggestion. I think I'm gonna try the multimethods way,
            that I didn't know about it.

            Comment

            Working...