Python: I don't understand the order of a function calling a function

时间:2016-04-21 22:44:56

标签: python list function list-comprehension

I'm following the book Data Science from Scratch by Joel Grus and they decribe the following code to create an identity matrix

def make_matrix(num_rows, num_cols, entry_fn):
    return [[entry_fn(i, j) 
            for j in range(num_cols)]           
            for i in range(num_rows)]

def is_diagonal(i, j):
    return 1 if i == j else 0

identity_matrix = make_matrix(5, 5, is_diagonal)

Although I can sort of see how this create an identity matrix, I'm having difficulties exactly understanding it.

The way I see it is that we call the function make_matrix with arguments 5, 5 and is_diagonal. At that point the code will thus go to the is_diagonal(i, j) for j in range(5) and so it will go to the function is_diagonal without having seen the outer loop ... for i in range(5). But if this is true, then it seems that the function is_diagonal will get as input variable (0,j), (1,j), ..., (4,j) and so is_diagonal doesn't get enough input variables (because j isn't defined). Could someone please explain where I'm going wrong in my train of thoughts?

1 个答案:

答案 0 :(得分:3)

That type of expression (a comprehension) is almost best of thought of in a Yoda sense: backwards it is. The last part of the expression is evaluated before the first.

This function is the equivalent of:

def make_matrix(num_rows, num_cols, entry_fn):
    ret = [] # you are dealing with an outer list 
    # and an outer loop
    for i in range(num_rows):
        cur = [] # and an inner list
        # And an inner loop
        for j in range(num_cols):
            curr.append(entry_fn(i,j)) # you add the result to the inner list
        # and once you're done with the inner loop, and the result to the outer list
        ret.append(cur) 
    # finally, complete the outer loop and return the result
    return ret

Both i AND j exist in the greater context of the function, even though i is defined after j in the more compressed version.