In terms of memory consumption, numpy arrays are more compact than Python tuples. The numpy array uses a single contiguous block of memory. All elements of a numpy array must have a declared type (for example, a 32-bit or 64-bit float.) A Python tuple does not necessarily use a continuous block of memory, and tuple elements can be arbitrary Python objects that usually consume more memory than numeric numeric types.
Thus, this problem is a freehand win for numpy (provided that the elements of the array can be stored as a numeric numeric type).
As for speed, I think the choice comes down to the question: "Can you design your code?"
That is, you can express your calculations as operations performed on all arrays by elements.
If the code can be vectorized, then numpy is likely to be faster than Python tuples. (The only case I could imagine where this might not be the case is if you have a lot of very small tuples. In this case, the overhead of forming numpy arrays and the one-time cost of importing numpy can drown out the advantage of vectorization.)
An example of code that could not be vectorized would be if your calculation included looking at, say, the first complex number in the array z , performing a calculation that produces an integer index idx , and then obtaining z[idx] , performing the calculation on that number which produces the next index idx2 , then extracts z[idx2] , etc. This type of calculation may not be vectorized. In this case, you can also use Python tuples, since you cannot use the power of numpy.
I would not worry about the speed of access to the real / imaginary parts of a complex number. I assume that the vectorization issue is likely to determine which method runs faster. (Although, by the way, numpy can convert an array of complex numbers into their real parts by simply going through a complex array, skipping each other float and viewing the result as a float. Moreover, the syntax is dead: if z is a complex numpy array, then z.real is the real parts of a floating-point array, which should be much faster than Python's clean approach to using understanding attribute lists: [z.real for z in zlist] .)
Just out of curiosity, what is the reason for your porting of C ++ code to Python?