-2

I have done this list comprehension to read a bunch of "pkl" files:

a = [pd.read_pickle("my_file"+str(i)+".pkl" for i in range(1, 18) if os.path.exists("my_file"+str(i)+".pkl")]

This is the only way I get it to work. If I add an else clause after the if it doesn't work. If I put the if clause before the loop it doesn't work. Could you explain why? If I do:

a = [pd.read_pickle("my_file"+str(i)+".pkl") if os.path.exists("my_file"+str(i)+".pkl") else print(i) for i in range(1, 18)]

This doesn't work, as opposed in many answers about list_comprehensions where that structure works.

Thanks.

David
  • 1,155
  • 1
  • 13
  • 35

1 Answers1

0
a = [pd.read_pickle("my_file"+str(i)+".pkl" if os.path.exists("my_file"+str(i)+".pkl") else your_alternate_value for i in range(1, 18)]

Or as I prefer to format it to prevent such long lines:

a = [
            pd.read_pickle("my_file"+str(i)+".pkl"
        if os.path.exists("my_file"+str(i)+".pkl")
        else your_alternate_value
    for i in range(1, 18)
]

List comprehension are a little hard for me to figure how to format. There might be another way that I would prefer, but it hasn't come to me yet.

Explanation

A list comprehension translates to a format like this

some_list = []
for ...:
    for/if ...
        ...
            ...
            some_list.append(something)

It's however many blocks you want, but only going deeper. Any block can contain only another block or the final appended value. Now, this makes sense when you consider that a list comprehension has no indentation. If you have two if blocks, how does the comprehension know which one the else belongs to?

The secret of my solution is that it isn't another block; it's part of what's being appended. The if/else is one expression, comparable to the ternary operator in other languages. Here's what's going on:

some_list = []
for ...
    some_list.append(something if blah else some_other_thing)

That's why the if/else is at the beginning.

Community
  • 1
  • 1
zondo
  • 19,901
  • 8
  • 44
  • 83