I'm new to python and came across this segment of code. Can someone help me with the syntax here? Maybe provide some comments on each line to how it's working? xs
is a list that contains dates.
data = {}
for title, d in tmpdata.items():
开发者_如何学运维data[title] = [x in d and d[x][statid] or 0 for x in xs]
data[title][-1] = maxs[statid]
If I had to guess, I'd say the most perplexing line to someone new to Python must be:
data[title] = [x in d and d[x][statid] or 0 for x in xs]
There is a lot going on here, and some of it uses a style that, although safe in this instance, is no longer recommended. Here is a more verbose form:
data[title] = []
for x in xs:
if x in d and d[x][statid]:
data[title].append(d[x][statid])
else:
data[title].append(0)
The construct condition and value-if-condition-is-true or value-if-condition-is-false
is an old-style form of the C ternary form condition ? value-if-condition-is-true : value-if-condition-is-false
. The given Python expression hides a latent bug that can crop up if the value-if-condition-is-true
is evaluated by Python as a "false-y" value - 0, [], ()
are all values that would be considered as false if used in a conditional expression, so you might have a problem if your value-if-condition-is-true
turned out to be one of these. As it happens in this case, if d[x][statid]
is 0, then we would assume a False result and go on and add a 0 to the list, which would be the right thing to do anyway. If we could just edit the verbose form, the simplest would be to remove the and d[x][statid]
as in:
data[title] = []
for x in xs:
if x in d:
data[title].append(d[x][statid])
else:
data[title].append(0)
Or use the new Python ternary form (which gives some people a rash, but I have grown accustomed to it - the ternary form, not the rash), which is written as:
value-if-condition-is-true if condition else value-if-condition-is-false
Or substituting into our verbose form:
data[title] = []
for x in xs:
data[title].append(d[x][statid] if x in d else 0)
So lastly, the list comprehension part. Whenever you have this kind of loop:
listvar = []
for some-iteration-condition:
listvar.append(some-iteration-dependent-value)
You can rewrite it as:
listvar = [some-iteration-dependent-value for some-iteration-condition]
and this form is called a list comprehension. It creates a list by following the iteration condition and evaluating the value for each iteration.
So you can now see how the original statement would be written. Because of the possible latent bug inherent in the old-style condition and true-value or false-value
, the ternary form or an explicit if-then-else is the preferred style now. The code should be written today as:
data[title] = [d[x][statid] if x in d else 0 for x in xs]
An explanation of the code is:
Initialize
data
to the empty dictionaryLoop through the key-value pairs in the dictionary
tmpdata
, calling the keytitle
and the valued
a. Add a new key-value pair to the
data
dictionary whose key istitle
and whose value is a list of the following: for eachx
in some (global?) listxs
, the valuex
itself ifd[x][statid]
is truthy otherwise 0.b. Overwrite the last cell of this new value with
maxs[statid]
There are some interesting pythonic structures here - list comprehensions and the and/or form of the conditional expression.
# Data initialization
data = {}
# for over all the element of the dictionary tmpdata
# title will get the index and d the data of the current element
for title, d in tmpdata.items():
#data[title]= a list containing each x contained in list xs
# the x value or 0 depening on the condition "d[x][statid]"
data[title] = [x in d and d[x][statid] or 0 for x in xs]
# Assign the value maxs[statid] to the last cell ( I think but not too sure)
data[title][-1] = maxs[statid]
精彩评论