0

I realize that the answer will vary depending upon the situation and purpose of the code. I was writing a class in a module and realized that redefining the operator methods of the class took quite a lot of code. We use inheritance for classes themselves, why not methods? It does, of course, slow it down a little, but it makes the code much more succinct.

Take the following classes for example:

class Ex1:
    def __init__(self, v):
        self.v = v
    def __add__(self, other):
        # Many lines of essential code
        return self.v + other.v
    def __sub__(self, other):
        # Many lines of essential code
        return self.v - other.v
    def __mul__(self, other):
        # Many lines of essential code
        return self.v * other.v
    def __truediv__(self, other):
        # Many lines of essential code
        return self.v / other.v

and:

import operator as ops

class Ex2:
    def __init__(self, v):
        self.v = v
    def __op__(self, other, op):
        if op == '+':
            op = ops.add
        elif op == '-':
            op = ops.sub
        elif op == '*':
            op = ops.mul
        elif op == '/':
            op = ops.truediv
        # Many lines of essential code
        return op(self.v, other.v)
    def __add__(self, other):
        return self.__op__(other, '+')
    def __sub__(self, other):
        return self.__op__(other, '-')
    def __mul__(self, other):
        return self.__op__(other, '*')
    def __truediv__(self, other):
        return self.__op__(other, '/')

Testing them with the timeit module I get this:

>>> timeit('Ex1(352) + Ex1(139)', 'from __main__ import Ex1')
1.2401711247332514
>>> timeit('Ex1(352) + Ex1(139)', 'from __main__ import Ex1')
1.2278626568422624
>>> timeit('Ex1(352) + Ex1(139)', 'from __main__ import Ex1')
1.2270929157546107
>>>
>>> timeit('Ex2(352) + Ex2(139)', 'from __main__ import Ex2')
1.6781722774976515
>>> timeit('Ex2(352) + Ex2(139)', 'from __main__ import Ex2')
1.6906975044787487
>>> timeit('Ex2(352) + Ex2(139)', 'from __main__ import Ex2')
1.678191572340893

So Ex2 is about 1.36 times slower than Ex1. But in some (rare) situations if one were to use the "work around" of Ex2, one would be able to eliminate hundreds of lines of code. But in general, would speed be valued over eliminating lines? Would a professional prefer to sacrifice a little speed to eliminate redundant lines of code?

Edit:

I realized that I can eliminate the if-statements by replacing the op parameter (from the symbol; eg. '+') with the actual function (eg. ops.add).

Clayton Geist
  • 422
  • 6
  • 14
  • I can't see how you eliminated lines there. If you have redundant lines, put those in a method, and call this method, than do the non-redundant stuff, but don't aggregate nicely seperated calls in one call just to seperate it again. – derM - not here for BOT dreams Apr 24 '17 at 06:47
  • `# If-elif statements are faster than dictionaries` Have you done any tests to show that? I truly doubt that statement. – DeepSpace Apr 24 '17 at 06:48
  • Also, tests I've done myself show the opposite. – DeepSpace Apr 24 '17 at 06:55
  • @DeepSpace You are right. I apologize. In my initial tests, I was creating the dictionary in __init__ instead of before __init__. It's the creation of the dictionary each time that is slower than the if statements. – Clayton Geist Apr 24 '17 at 07:16
  • @DeepSpace In fact, further testing has shown that somehow a dictionary look-up is faster than simply providing the functions themselves as the parameter. Do you know why that is? – Clayton Geist Apr 24 '17 at 07:22
  • 1
    @ClaytonGeist See this answer and the links it points to: http://stackoverflow.com/a/1963514/1453822 Dictionary lookup time in Python is O(1) on (even more than) average. – DeepSpace Apr 24 '17 at 07:46
  • @DeepSpace That's all fine, but I still don't understand how a lookup would be faster than actually inputting the value that would be returned by the lookup. How would `d={key:func...}; d[key](val)` be faster than `func(val)`? – Clayton Geist Apr 24 '17 at 08:23
  • @ClaytonGeist You can use `d[key](val)` instead. – Roland Smith Apr 24 '17 at 09:37

0 Answers0