Cython with variable-length arrays Dynamically growing arrays are a type of array. They are very useful when you don't know the exact size of the array at design time. First you need to define an initial number of elements. (Wikipedia)

I have written a Python solution and converted it to Cython.
Cython can be used to improve the speed of nested for loops in Python.
Where my Cython code is slightly faster.
My Cython solution is obviously not the fastest.
I am trying to perform a nested for loop similar to the one in my Python code as fast as possible in Cython.

It would help to have some experience in C, which I don't.
The main problem that I ran into is that Cython has different scoping rules to Python.
Since C and Python have different scoping rules.
In other words, we cannot create a new vector in the loop and assign it to the same name.

My solution works but is too slow.
Can anyone improve Cython code above by using a more C like approach.
Python
import numpy as np

my_list = [1,2,3]
n = 10
a = 0.5

Estimate_1_list = []
Estimate_2_list = []

for l in my_list:

    # Resizable matrices
    a_mat = np.zeros((l,n+1),float)
    b_mat = np.zeros((l,n+1),float)
    
    for i  in range(n):
        t = i*a
        
        for j in range(l):
            
            # Fill matrices
            a_mat[j,i+1] = a_mat[j,i+1] + np.random.random()
            
            b_mat[j,i+1] = a_mat[j,i+1]/(2*t+3)
    
    # Append values of interest to use at different values of matrix size
    Estimate_1_list.append(np.mean(a_mat[:,n]))
    Estimate_2_list.append(np.std(a_mat[:,n]))   
results = [Estimate_1_list,Estimate_2_list]

Cython
import cython
# Load cython extension
%load_ext Cython

%%cython
import numpy as np

def my_function(list my_list, int n, int a ):
cdef list Estimate_1_list = []
cdef list Estimate_2_list = []
cdef int l,i,t,j
for l in my_list:

    # Resizable matrices (could I use memory view?)
    a_mat = np.zeros((l,n+1),float)
    b_mat = np.zeros((l,n+1),float)

    for i  in range(n):
        t = i*a

        for j in range(l):

            # Fill matrices
            a_mat[j,i+1] = a_mat[j,i+1] + np.random.random()

            b_mat[j,i+1] = a_mat[j,i+1]/(2*t+3)

    # Append values of interest to use at different values of matrix size
    Estimate_1_list.append(np.mean(a_mat[:,n]))
    Estimate_2_list.append(np.std(a_mat[:,n]))  
    
# Return results 
results = [Estimate_1_list,Estimate_2_list]
return results

Tests
# Test cython to show that the function is running
my_list = [1,2,3]
n = 10
a = 0.5
my_function(my_list, n, a)

[[0.13545224609230933, 0.6603542545719762, 0.6632002117071227],
 [0.0, 0.19967544614685195, 0.22125180486616808]]
In addition to Reinderien's answer, may I suggest:
Yes, Use Memoryviews to speed up access
In addition to the code you have, I would also type the a_mat and b_mat matrixes as double[:,::1] following the Typed Memoryviews guide. (the &quot;1&quot; means contiguous and is allows for slightly faster access). You are right in that you can not cdef declare variables in a loop, but you can cdef declare variables at the top of the function, and reassign within the loop.

    ...
    cdef list Estimate_1_list = []
    cdef list Estimate_2_list = []
    cdef int l,i,t,j
    cdef double[:, ::1] a_mat # declare here
    cdef double[:, ::1] b_mat
    for l in my_list:
        
        # Resizable matrices (could I use memory view?)
        a_mat = np.zeros((l,n+1),float) # assign in loop
        b_mat = np.zeros((l,n+1),float)
    ...


Turn off Boundscheck And Wrap Around check
Once you are sure that code is bug free. You can locally turn off bounds and wraparound checks using the decorators or with statements for additional speed up. (Compiler Directives, Local Directives)