[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