Peter
Peter

Reputation: 371

Python: Complex for-loops

I am working through some code trying to understand some Python mechanics, which I just do not get. I guess it is pretty simple and I also now, what it does, but i do not know how it works. I understand the normal use of for-loops but this here... I do not know.

Remark: I know some Python, but I am not an expert.

np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])

The second piece of code, I have problems with is this one:

for i in range(len(u)):
        for j in range(len(v)):
            tmp+=[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]

How does the innermost for-loop work? And also what does the if do here?

Thank you for your help.

EDIT: Sorry that the code is so unreadable, I just try to understand it myself. S, rm are numpy matrices, someFunction returns an array with scalar entries, andtmp is just a help variable

Upvotes: 1

Views: 7091

Answers (2)

armatita
armatita

Reputation: 13465

There are quite a few different concepts inside your code. Let's start with the most basic ones. Python lists and numpy arrays have different methodologies for indexation. Also you can build a numpy array by providing it a list:

S_list  = [[1,2,3], [4,5,6], [7,8,9]]
S_array = np.array(S_list)

print(S_list)
print(S_array)

print(S_list[0][2]) # indexing element 2 from list 0
print(S_array[0,2]) # indexing element at position 0,2 of 2-dimensional array

This results in:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1 2 3]
 [4 5 6]
 [7 8 9]]
3
3

So for your first line of code:

np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])

You are building a numpy array by providing it a list. This list is being built with the concept of list comprehension. So the code inside the np.array(...) method:

[[[S[i,j]] for i in range(order+1)] for j in range(order+1)]

... is equivalent to:

order     = 2
full_list = []
for j in range(order+1):
    local_list = []
    for i in range(order+1):
        local_list.append(S_array[i, j])
    full_list.append(local_list)

print(full_list)

This results in:

[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

As for your second snippet its important to notice that although typically numpy arrays have very specific and constant (for all the array) cell types you can actually give the data type object to a numpy array. So creating a 2-dimensional array of lists is possible. It is also possible to create a 3-dimensional array. Both are compatible with the indexation rm[i,j][k]. You can check this in the following example:

rm = np.array(["A", 3, [1,2,3]], dtype="object")
print(rm, rm[2][0]) # Acessing element 0 of list at position 2 of the array

rm2 = np.zeros((3, 3, 3))
print(rm2[0, 1][2])  # This is also valid

The following code:

[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]

... could be written as such:

some_list = []
for k in range(len(rm[i,j])):
    if rm[i, j][k]: # Expecting a boolean value (or comparable)
        a_list = rm[i,j][k]*someFuction(name,u[i],v[j])
        some_list.append(a_list[k])

The final detail is the tmp+=some_list. When you sum two list they'll be concatenated as can been seen in this simple example:

tmp = []
tmp += [1, 2, 3]
print(tmp)
tmp += [4, 5, 6]
print(tmp)

Which results in this:

[1, 2, 3]
[1, 2, 3, 4, 5, 6]

Also notice that multiplying a list by a number will effectively be the same as summing the list several times. So 2*[1,2] will result in [1,2,1,2].

Upvotes: 4

krflol
krflol

Reputation: 1155

Its a list comprehension, albeit a pretty unreadable one. That was someome doing something very 'pythonic' in spite of readablity. Just look up list comprehensions and try to rewrite it yourself as a traditional for loop. list comprehensions are very useful, not sure I would have gone that route here.

The syntax for a list comprehension is

[var for var in iterable if optional condition]

So this bottom line can be rewritten like so:

for k in range(len(rm[i,j]):
    if rm[i,j][k]:
        tmp+= rm[i,j][k]*someFunction(name,u[i],v[j])[k]

Upvotes: 2

Related Questions