My question is: despite all this, is the latest version of the code more readable than the first? This seems like a more monolithic expression that must be deceived immediately.
I would say that this is a more readable, although not necessarily the most readable option. Yes, this is more logical on one line, but it is outweighed by three facts.
Firstly, you can still mentally decompose it into smaller parts and understand them individually before combining them. I immediately see that you are summing something up (at this point I do not need to know what you are summing up). I also see that you get entries from the scoretable for each letter , the default is 0 if not (at this point I do not need to know what is happening with this list). These things can be identified and understood independently. Secondly, very few, several independent parts, maybe two or three. It is unreasonable to immediately realize that the "monolithic" aspect is more of a problem when dozens of problems sit next to each other.
Finally, the perceived advantage of the first version,
compared to the previous version, where you have a chance to create a block value from smaller, more atomic fragments.
also a problem: when I start reading, I see a for loop. This is good, but in reality it does not tell me anything yet (except that there is a cycle that does not help me understand the logic, but only its implementation). Therefore, I must remember this and read further, in order to later decide what this cycle means. To some extent, this applies to any code, but it gets worse as more code. Similarly, the score = 0 line does not mean anything in itself, it is just one tiny implementation detail that no one needs to know to understand that this function calculates the scrabble word score by adding a score for each of the letters of the word.
When you read your imperative cycle, you need to keep track of a lot of mutable variables, control flow, etc., to figure out what is going on, and you need to combine the parts. In addition, it is simply more characters to read, and therefore it will take more time to understand, even if the understanding was instantaneous anyway. You must consider these costs. Whatever you win, if every line was easier, it was lost.
However, the next version is possible , precisely because it divides the two parts of the algorithm into separate lines:
def scrabble_score(word, scoretable): letter_scores = [scoretable.get(letter, 0) for letter in word] return sum(letter_scores)
But the difference is quite small, it is quite subjective. Both are beautiful and much better than your first version. (Oh, one more thing: I would use a generator expression, not a list comprehension, I just kept the list comprehension to minimize noise.)