Making a 2D dict readable I am building a 2d dictionary with an altered list at the end Afterwords I want to find the min of each list. Is there a better way to do it? Better being faster or at least less of an eyesore.

#dummy function, will be replaced later so don't worry about it.
def alter(x, y, z,):
    a = list(x)
    for i, val in enumerate(x):
         a[i] = val + y + z
    return a

masterStats = {}
askStats = [0, 1, 2]
for numberServed in range(3):
    masterStats[numberServed] = {}
    for timeToServe in range(3):
        masterStats[numberServed][timeToServe] = alter(askStats, numberServed, timeToServe)

for numberServed in masterStats.keys():
    for timeToServe in masterStats[numberServed].keys():
        print(min(masterStats[numberServed][timeToServe]))


for numberServed in masterStats.keys():
    print(numberServed)
    for timeToServe in masterStats[numberServed].keys():
        print("    " + str(timeToServe))
        print("        " + str(masterStats[numberServed][timeToServe]))
Python's variable names are conventionally named lowercase_width_underscores.

Loop using .items() not .keys() if you will need the values, so your final loop can be:

for numberServed, numberServedStats in masterStats.items():
    print(numberServed)
    for timeToServe, timeToServeStats in numberServedStats,items():
        print("    " + str(timeToServe))
        print("        " + str(timeToServeStats))


The whole thing can be made more efficient by using numpy:

askStats = numpy.array([0, 1, 2])

x = askStats[None,None,:] # put askStats in the third dimension
y = numpy.arange(3)[:, None, None] # put number served in the first dimension
z = numpy.arange(3)[None, :, None] # put time to serve in the second dimension

stats = x + y + z # same as in alter


We create a new array by adding together three existing arrays. The [:,None, None] parts control how they are added. Essentially, the colon indicates the column the data will be spread across. The None indicates where the data will be duplicated. So numpy.arange(3)[:,None] gets treated like

[ 
    [0, 0, 0],
    [1, 1, 1],
    [2, 2, 2]
]


Whereas numpy.arange(3)[None, :] gets treated like

[
    [0, 1, 2],
    [0, 1, 2],
    [0, 1, 2]
]


This lets us do the complete loop and adjust function in just that one expression.

for line in stats.min(axis=2).flatten():
    print(line)


The min method reduces the 3 dimensional array to 2d array by minimizing along dimension 2. Flatten() converts that 2d array into one long one dimensional array.

for row_index, row in enumerate(stats):
    print(row_index)
    for col_index, col in enumerate(row):
        print("    ", col_index)
        print("        ", col)


It probably won't help much here, but for bigger cases using numpy will be more efficient.