[Tutor] Luke, thanks a lot , here is the perfect code (as per ur suggestion)

Kent Johnson kent37 at tds.net
Fri Oct 6 00:40:54 CEST 2006


Asrarahmed Kadri wrote:
> What is this??? I cannot understand a single character.. Explain this in 
> length.
> 
>     *list1 = [ [ locals()["_[1]"][i-1][j-1]+locals()["_[1]"][i-1][j] if
>     (j !=
>     0 and j != i) else 1 for j in range(i+1) ] for i in
>     range(num_of_lines) ]

OK, I guess I asked for that. Remember, I did say this was hideous, I 
would never use this for anything other than a newsgroup posting.

Here is your original code, more or less:

list1 = []
for i in range(5):
     flag = 0
     tmp = []
     for j in range(i+1):
         if flag == 0 or j == i:
             tmp.append(1)
             flag = 1
         else:
             tmp.append(list1[i-1][j-1]+list1[i-1][j])
     list1.append(tmp)

First let's get rid of flag, it isn't needed:

list1 = []
for i in range(5):
     tmp = []
     for j in range(i+1):
         if j == 0 or j == i:
             tmp.append(1)
         else:
             tmp.append(list1[i-1][j-1]+list1[i-1][j])
     list1.append(tmp)

Now replace the inner if/else with a conditional expression inside the 
call to append(). A conditional expression has the form (a if b else c) 
where b is the condition being tested and a and c are the two values. 
The if/else becomes this monster:

tmp.append(list1[i-1][j-1]+list1[i-1][j] if (j!=0 and j!=i) else 1)

I inverted the condition so I could put the more common case first. Now 
the whole program looks like this:

list1 = []
for i in range(5):
     tmp = []
     for j in range(i+1):
         tmp.append(list1[i-1][j-1]+list1[i-1][j] if (j!=0 and j!=i) else 1)
     list1.append(tmp)

The inner loop is now ready to be replaced with a list comprehension. In 
general, a loop of the form

tmp = []
for i in x:
   tmp.append(f(i))

can be replaced with the equivalent list comprehension

tmp = [ f(i) for i in x ]

With this change the program is down to this:

list1 = []
for i in range(5):
     tmp = [ list1[i-1][j-1]+list1[i-1][j] if (j!=0 and j!=i) else 1 for 
j in range(i+1) ]
     list1.append(tmp)

This is again in the form of a loop that can be replaced by a list 
comprehension, this time to create list1. The problem is that the 
expression in the list comprehension has to refer to the list being 
built, and this list is not normally available because the name has not 
yet been bound. This is where the cookbook hack comes in play - within a 
list comprehension, the list being built can be referenced as 
locals()["_[1]"]. Refer to the cookbook recipe for details.

So within the list comp,
list1[i-1][j-1] becomes locals()["_[1]"][i-1][j-1] and
list1[i-1][j] becomes locals()["_[1]"][i-1][j].

This brings us to the final form:

list1 = [ [ locals()["_[1]"][i-1][j-1]+locals()["_[1]"][i-1][j] if (j!=0 
and j!=i) else 1 for j in range(i+1) ] for i in range(5) ]

or, with slightly nicer formatting:

list1 = [
     [ locals()["_[1]"][i-1][j-1]+locals()["_[1]"][i-1][j] if (j!=0 and 
j!=i) else 1
         for j in range(i+1)
     ] for i in range(5)
]

Kent



More information about the Tutor mailing list