# Create a list of all words in a string, the length of a word preceding it if even

from typing import List
import itertools

my_string = "Atunci când citești un text trebuie să fii capabil să identifici ideea principală a textului și să o poți formula în propriile tale cuvinte"
my_list : List[str] = my_string.split(' ')

my_list2 : List[str| int] = [item for lis in list((len(word), word) if len(word) % 2 == 0 else [word] for word in my_list) for item in lis]

print(my_list2)

assert my_list2 == [6, 'Atunci', 4, 'când', 'citești', 2, 'un', 4, 'text', 'trebuie', 2, 'să', 'fii', 'capabil', 2, 'să', 10, 'identifici', 'ideea', 10, 'principală', 'a', 8, 'textului', 2, 'și', 2, 'să', 'o', 4, 'poți', 'formula', 2, 'în', 'propriile', 4, 'tale', 'cuvinte']


The code above solves a simple problem of returning a list with all the words from a string, but if the word has an even length, the length should be included before the word in the new list.
After doing the list comprehension, I find it hard to explain it to someone else, I'm new to Python and the code works as intended, any advice?

Make the code simpler first. You question is an important one: how does one take a complex process in a computer algorithm and describe it in terms that are readily understood? Most software engineers place too little emphasis on that topic. But in your case, the biggest problems stem not from the absence of understandable English explanations but from the absence of simplicity and clarity in the code itself. If the code is made clearer, the explanations are usually much easier to craft.

Put code in functions. All of it. This discipline has many benefits. One of them is that we will be forced to given your algorithm some kind of name.

Give variables substantive names. Your current names are generic, providing no useful information other than data types (which were already obvious from the code). Rather than my_string, use something concrete like text. Rather than my_list, use something direct like words.

Don't cram everything into one mega-operation. Your list comprehension requires careful reading to figure out is happening. Break the steps down into smaller parts that the reader can grasp more easily. In the illustration below, I used a simple helper function that was easy to explain in a code comment. The existence of that helper also made the resulting list comprehension easy to explain. Someone working on this code a year from now would have no trouble figuring out what it does.

def main():
expected = [6, 'Atunci', 4, 'când', 'citești', 2, 'un', 4, 'text', 'trebuie', 2, 'să', 'fii', 'capabil', 2, 'să', 10, 'identifici', 'ideea', 10, 'principală', 'a', 8, 'textului', 2, 'și', 2, 'să', 'o', 4, 'poți', 'formula', 2, 'în', 'propriile', 4, 'tale', 'cuvinte']
text = "Atunci când citești un text trebuie să fii capabil să identifici ideea principală a textului și să o poți formula în propriile tale cuvinte"
got = even_lengths_and_words(text)
print(got == expected)

def even_lengths_and_words(text):
# Helper function: takes a word. Yield its length (if even)
# and then yields the word.
def gen(w):
n = len(w)
if n % 2 == 0:
yield n
yield w

# Splits text into words. Returns a list built from
# all values emitted by the helper.
return [
x
for word in text.split()
for x in gen(word)
]

if __name__ == '__main__':
main()


Next steps: reconsider your data structure. The end result is an odd data structures: a list of word lengths (but only if even) plus words. The difficulty of finding a good name for the function (I tried my best) is basically a warning sign to you that your data might be ill-conceived. Things that are difficult to name and explain are often (not always) flawed in concept. I would encourage you to do some thinking about whether a different approach to the data would help your project.

• even_lengths_and_words() would profit from a docstring. The comment on gen() almost makes one (for gen()). Mar 15 at 10:42