1

Is there a way of using the list-comprehension "syntax" in functions, to reduce calculation/calls (a bit like try/catch) e.g a way of writing

customers=dict

for customer in customers:
  if movie not in customers[customer]:
          customers[customer].append(movie)

as

for customer in customers:
  p.append(movie) if movie not in p=customers[customer]

if the call/operation p was very heavy, thus it makes a big deal, if it is called once or twice

CutePoison
  • 4,679
  • 5
  • 28
  • 63
  • 3
    `p` already exists as `customer` does it not? list comprehensions should be used when you want a list as an output, not to reduce lines of code – Sayse Oct 16 '19 at 12:09
  • You are effectively trying to use a comprehension for its side effects (appending to existing lists), which is discussed [here](https://stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects). – glibdud Oct 16 '19 at 12:15
  • it is not about list-comprehension, but to reduce the call `customers[customer]` from two to one – CutePoison Oct 16 '19 at 12:15
  • 1
    Loop the values instead of the keys, also, you can get more performance by using a `set` for `movies` instead of a list – Tarifazo Oct 16 '19 at 12:16

3 Answers3

3

You can use the items method of a dict in a list comprehension:

[ expression for key,val in customers.items() ]

so you could abuse it to have the side-effect of appending:

[ val.append(movie) for key,val in customers.items() if movie not in val ]

The actual value of the list-comprehension is almost useless: it'll be a list of None (but its length will tell you how many val did not contain movie).

Sometimes, shorter is not better style. I think this may be one of them.

Edit: just realised key is unused, so the .values() method is better (I find a use for it so rarely I forgot about it!)

[ val.append(movie) for val in customers.values() if movie not in val ]
nigel222
  • 7,582
  • 1
  • 14
  • 22
0

Not sure what kind of "calculation/calls" you are trying to reduce, but if it is the double lookup of customers[customer], you can do it like this:

for movies in customers.values():
    if movie not in movies:
        movies.append(movie)

.values() iterates over the values of the dict (so in your case, the list of movies for each customer), so it avoids iterating on the customers and looking up the list of movies twice. That works assuming customers is a dict of lists as values. You can even enhance that with a dict of sets:

for movies in customers.values():
   movies.add(movie)
Guillaume
  • 5,497
  • 3
  • 24
  • 42
  • It is for each `customer` i want to check, if that movie is already in his list, i.e the call `customers[customer]` (list of movies) is called twice: one for checking if `movie` is in that list and once more when we append it. – CutePoison Oct 16 '19 at 12:20
0

One-line code:

[movies.append(movie) for movies in customers.values() if movie not in movies]

dict.values() returns a list-like object of the values of a dictionary, excluding the keys. The line above evaluates a list of return values of list.append, but list.append returns None, and the list is discarded anyways.


What I recommend is to actually write out the full logic:

for movies in customers.values():
    if movie not in movies:
        movies.append(movie)

and to use list comprehension only when you actually need the list. It will only confuse those who don't understand list comprehension, and it does not provide any speedup or cleaner code.

Also, if you don't want repeating items in a list, consider a set, which contains distinct elements and provides a speedup.

hzahnuwen
  • 136
  • 7