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?
答案 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.