Let's find out:
In [8]: def with_assignment(arr, x, y):
...: a = arr[x][y]
...: return a
...:
In [9]: dis.dis(with_assignment)
2 0 LOAD_FAST 0 (arr)
3 LOAD_FAST 1 (x)
6 BINARY_SUBSCR
7 LOAD_FAST 2 (y)
10 BINARY_SUBSCR
11 STORE_FAST 3 (a)
3 14 LOAD_FAST 3 (a)
17 RETURN_VALUE
In [10]: def without_assignment(arr, x, y):
....: return arr[x][y]
....:
In [11]: dis.dis(without_assignment)
2 0 LOAD_FAST 0 (arr)
3 LOAD_FAST 1 (x)
6 BINARY_SUBSCR
7 LOAD_FAST 2 (y)
10 BINARY_SUBSCR
11 RETURN_VALUE
So adding the assignment adds two bytecode instructions, a STORE_FAST
and LOAD_FAST
. So, strictly speaking, using the value directly is faster. But by how much?
In [34]: arr = [range(100) for _ in xrange(1000)]
In [35]: %timeit without_assignment(arr, random.randint(0,999), random.randint(0,99))
The slowest run took 9.75 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.83 µs per loop
In [36]: %timeit with_assignment(arr, random.randint(0,999), random.randint(0,99))
The slowest run took 10.57 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.8 µs per loop
So, for relatively small arrays it seems like the difference is a few microseconds. If you're trying to make your code more efficient, this probably isn't the bottleneck.
If you're going to reuse the value, obviously store it so you don't have to recalculate it.