The whole exercise turns on one detail of one method. This solved function shows it — read the input carefully and then the output.
def word_lengths(sentence):
return [len(word) for word in sentence.split()]
# word_lengths(' the quick fox ') -> [3, 5, 3]
# note: no zero-length words, despite all that whitespace
- split() and split(' ') are different functions
Called with no argument, split treats any run of whitespace as one separator and throws away the empty pieces at each end. Called with ' ' it splits on every single space, so ' a b '.split(' ') gives you ['', '', 'a', '', 'b', ''] — five surprises waiting to be indexed.
- The empty case comes free
''.split() is [], so the comprehension produces [] and nothing special has to be written for it. Getting the empty case for free is usually a sign you picked the right tool.
- Build the pieces, then join
Producing one small thing per word and combining them at the end is the shape of most text work in Python. Reach for it before reaching for a running string you keep adding to.
Two steps: get the words out of the string, then turn each word into a letter and a dot. The first step is one method call, and which form of it you choose decides whether the messy-whitespace case works.
name.split() with no argument gives you the words and drops the empty pieces. For each word, word[0] is its first character and .upper() makes it a capital.
Produce one small string per word — the uppercase first letter plus a dot — and join them with ''.join(...). No separator is needed because the dot is already part of each piece.
def initials(name): return ''.join(____[0].____() + '.' for ____ in name.____())
def initials(name):
return "".join(word[0].upper() + "." for word in name.split())
It is tempting to write '.'.join(...) and get 'A.L' — then bolt a dot on the end, and then special-case the empty string so you do not return a lone '.'. Making each piece self-contained removes both problems at once. When a join needs fixing up afterwards, the pieces are usually drawn wrong.
There are no brackets inside join() — that is a generator expression, so no intermediate list is built. For a name it is irrelevant; for a million rows it is the difference between steady memory and a spike. The habit is free, so form it here.
Indexing the first character of a string crashes on an empty one. It is safe in this line precisely because split() with no argument never yields an empty word. Change that call and the indexing becomes a bug — which is exactly what happens to solutions built on split(' ').
Do not treat this as a general solution to human names. It quietly assumes names are Latin-script, that word order carries meaning, and that a particle like 'van' or 'de' deserves its own initial — none of which hold everywhere. It is fine for an avatar badge. For anything legal, identity-bearing, or user-facing at scale, ask people what they want displayed and store that.
- Cap the output at two initials — first and last word — for a fixed-width avatar, while still handling one-word and empty names.
- Handle a name written 'Lovelace, Ada' as well as 'Ada Lovelace', and decide how the function should know which form it was given.
- Preserve particles: make 'ludwig van beethoven' produce 'L.v.B.' rather than 'L.V.B.', and write down the rule you chose before you code it.