1

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

Peter
  • 341
  • 1
  • 4
  • 16
  • this is not readable at all... – eagle Apr 04 '18 at 15:13
  • Someone clearly wrote this as a joke. Possibly on his/herself. Why the DV? Seems like a legit question... – Jared Smith Apr 04 '18 at 15:15
  • Possible duplicate of [Explanation of how list comprehension works?](https://stackoverflow.com/questions/20639180/explanation-of-how-list-comprehension-works) – eyllanesc Apr 04 '18 at 15:15
  • 2
    If you intend for no one to ever fathom being able to read your code, then this thoroughly accomplishes it's task. – rahlf23 Apr 04 '18 at 15:16
  • 1
    Guys this is obviously a player of CodeGolf... Look how short and messy it iss! – L_Church Apr 04 '18 at 15:18
  • @Peter in (kinda sorta) answer to your question, it's impossible for us to tell what's going on here, as we don't know what `S`, `tmp`, `order` and `rm` are. And every place where the comma is used in an array/list index (e.g. `rm[i,j]` should AFAIK raise an exception. – Jared Smith Apr 04 '18 at 15:21
  • Updated the quesition. – Peter Apr 04 '18 at 15:27
  • The part with list comprehension answers the first part, but how does the `if`-statement work here. – Peter Apr 04 '18 at 15:31
  • 1
    hi @peter, what about to [RTFM](https://en.wikipedia.org/wiki/RTFM): Here it is: [5.1.3. List Comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) – dani herrera Apr 04 '18 at 15:36
  • @danihp thats exactly what I was looking for. Thank you so much :D – Peter Apr 04 '18 at 15:38

2 Answers2

4

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].

armatita
  • 12,825
  • 8
  • 48
  • 49
2

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]
krflol
  • 1,105
  • 7
  • 12
  • Hmmm... +1 this answers part of the question, -1 this has no explanation of the obsfucated line. EDIT: apparently other people are harsher than me. – Jared Smith Apr 04 '18 at 15:18