Apologies in advance for the obscure title. I wasn't sure how to phrase what I encountered.
Imagine that you have a title of a book alongside its author, separated by -
, in a variable title_author
. You scraped this information from the web so it might very well be that this item is None
. Obviously you would like to separate the title from the author, so you'd use split. But in case title_author
is None to begin with, you just want both title
and author
to be None
.
I figured that the following was a good approach:
title_author = "In Search of Lost Time - Marcel Proust"
title, author = title_author.split("-", 1) if title_author else None, None
print(title, author)
# ['In Search of Lost Time ', ' Marcel Proust'] None
But to my surprise, title
now was the result of the split and author
was None
. The solution is to explicitly indicate that the else clause is a tuple by means of parentheses.
title, author = title_author.split("-", 1) if title_author else (None, None)
print(title, author)
# In Search of Lost Time Marcel Proust
So why is this happening? What is the order of execution here that lead to the result in the first case?
title, author = title_author.split("-", 1) if title_author else None, None
is the same as:
title, author = (title_author.split("-", 1) if title_author else None), None
Therefore, author
is always None
Explaination:
From official doc
An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.
That is to say, the interrupter will look for (x,y)=(a,b)
and assign value as x=a
and y=b
.
In your case, there are two interpretation, the main differece is that :
title, author = (title_author.split("-", 1) if title_author else None), None
is assigning two values (a list or a None and a None) to two variables and no unpacking is needed.
title, author = title_author.split("-", 1) if title_author else (None, None)
is actually assigning one value (a list or a tuple) to two variable, which need an unpacking step to map two variables to the two values in the list/tuple.
As option 1 can be completed without unpacking, i.e. less operation, the interrupter will go with option 1 without explicit instructions.