title: Fastest way to sum two lists of items with each other in python
body: <p>I have a bit of a strange request that I'm looking to solve with utmost efficiency; I have two lists <code>list_1</code> and <code>list_2</code>, which are both the same length and will both only ever contain integers greater than or equal to 0. I want to create a new list <code>list_3</code> such that every element <code>i</code> is the sum of the elements at position <code>i</code> from <code>list_1</code> and <code>list_2</code>. In python, this would suffice:</p>
  
  <p><code>list_3 = [list_1[i] + list_2[i] for i in range(len(list_1))]</code></p>
  
  <p><strong>However</strong>, there is a catch. For every <code>i</code> such that <code>0 &lt;= i &lt; len(list_1)</code>, if the item at position <code>i</code> (i.e. <code>list_1[i]</code>) is 0, then the sum of <code>list_1[i]</code> and <code>list_2[i]</code> should <strong>also be zero</strong>.</p>
  
  <p>What would be the most efficient way to do this? I have to perform this operation on list with 323 elements in it and it needs to be for a game, so it should be able to run easily 60 times per second whilst allowing a lot of extra time for other things to calculate in the game. I was wondering if there might be any fancy numpy way of doing it but I'm not well versed enough with numpy to know for sure.</p>
  
  <p>EDIT:</p>
  
  <p>In terms of simply summing two elements, some common expressions are:</p>
  
  <pre><code>list_3 = [list_1[i] + list_2[i] for i in range(len(list_1))]
  list_3 = [sum(t) for t in zip(list_1, list_2)]
  list_3 = numpy.add(list_1, list_2)
  </code></pre>
  
  <p>EDIT 2:</p>
  
  <p>I know of conditional list comprehensions, but I'm wondering if there is a faster method than that.</p>
  
  <p>EDIT 3:</p>
  
  <p>Here are some of the timings of methods given:</p>
  
  <pre><code>&gt;&gt;&gt; import timeit
  &gt;&gt;&gt; setup='''
  import random
  list_1 = [random.randint(0, 323) for i in range(323)]
  list_2 = [random.randint(0, 323) for i in range(323)]
  '''
  &gt;&gt;&gt; timeit.timeit('list_3 = [list_1[i] + list_2[i] if list_2[i] else 0 for i in range(len(list_1))]', setup=setup, number=1)
  6.005677381485953e-05
  &gt;&gt;&gt; timeit.timeit('list_3 = [x + y if y else 0 for x, y in zip(list_1, list_2)]', setup=setup, number=1)
  3.604091037417601e-05
  </code></pre>
  
  <p>Anything faster?</p>
  
  <p>EDIT 4:</p>
  
  <p>Here is an explanation as to what I need this for: I'm working on a video game that requires a system of checking the state of certain keys on the keyboard from time to time. The way the system needs to work is that the longer a key is pressed down, the higher a counter for said key increases. Once that key is released, the counter is set back to 0. This needs to be done for all keys, not just a select few. It's currently a bottleneck compared to the rest of the program, according to <code>cProfile</code>.</p>
  
  <p>Here is the code that generates the state of each key in the keyboard (it uses <code>pygame</code> to grab the key states):</p>
  
  <pre><code>class KeyState:
      """
      An object representing the state of the keyboard input at a given frame.
  
      The KeyState is a global replacement for pygame's event system (or
      pygame.keys.get_pressed()). It provides a simple interface for updating
      and retreiving the states of keys in real time.
  
      To retreive and store the current key information, simply call
      the update() method. To retreive the given information about a
      key, use the get_state(key) method where key is any pygame key
      (i.e. pygame.K_RSHIFT, etc.).
      """
  
      def __init__(self):
         self.current_frame = pygame.key.get_pressed()
  
      def update(self):
          """
          Retreive the current key state data.
          """
          new_frame = pygame.key.get_pressed()
          self.current_frame = [state + new_frame[i] if new_frame[i] else 0 for i, state in enumerate(self.current_frame)]
  
      def get_state(self, key, strict=True):
          """
          Retreive the current state of a given key.
  
          &gt;= 1 - Pressed
          0    - Unpressed
          """
          try: 
              return self.current_frame[key]
          except KeyError:
              if strict:
                  raise
  </code></pre>