I appreciate everyone’s interest and consideration in addressing this question. I’m just trying to understand the philosophical foundation of using list comprehension only for functional style procedures. (Side note: I recently watched the 2018 Lex Fridman interview in which GvR said that he was challenged extensively by folks who wanted to assert that his view of PEP 572 and what aligns with Python’s philosophy was incorrect, so moving the discussion to a philosophical level is no magic wand.)
The damage is obvious in these examples, as is the unreadability of gruesome constructions.
[1]
These cases are self-evident, though. There’s something more subtle in the side effects of list comprehensions because they appear to be useful shorthand in certain cases, such as mutating short lists in some trivial side process. To rephrase the question within the context of abuse: what is the damage in using list comprehension for its side effects? We can assert that something is bad/ugly/abuse or only intended for X, but what’s the philosophical situation? What’s the core-level case against this beyond style, opinion, or purist dogma?
@cameron hit on the philosophical question with the point that list comprehension creates a list in memory and therefore wastes resources. This is an adverse and objective (not based on opinion) outcome. But what happens to this potential consumption of memory if the comprehension isn’t assigned to anything? I’m genuinely interested in knowing so I can understand Python better.
This is along the same lines. What are the inefficiencies?
Readability doesn’t always prevent this shorthand for:
because a simple list comprehension with side effects can be very transparent, just as a simple single-line if:
can be more readable than when broken into two lines:
(else: break
). (Off-topic example simply for illustration. No need to respond, especially since this is already the subject of a recent topic.)
I find this perfectly readable:
ints = [1,2,3,4,5,6,7,8,9]
[ints.remove(x) for x in ints[::-1] if x %2 == 1] #removes the odd numbers
(Yes, it iterates backwards to ensure that the tail of the shrinking list doesn’t slip under the iteration. Yes, it’s probably “too clever” and yes, that was a fun puzzle to work out. )
As it turns out, the list methods might be the only mutations that can operate in a list comprehension, so there’s some built-in self-policing. Pylance in VS Code complains about the following assignment and can’t resolve the scope for the first instance of ’ x
':
[x+=1 for x in ints if x %2 == 1]
#would bump odd numbers in the list to even--if it would run
(This is also quite readable if you know the grammar of conditional list comprehensions and the += shorthand. That’s a moot point, though, since it doesn’t run.)
I do agree that such a construct as [ints.remove(x) for x in...]
can be abused. So can many legitimate functions. Maybe I just stumbled upon an unintended artifact while noodling around with list comprehensions. Is that worth publicly bonking someone with a hammer or other blunt instrument about…or with your iPhone?
@Vbrozik, did you make this up or did you pull it out of some Hall of Shame?
print(*filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,map(lambda x,y=y:y%x,range(2,int(pow(y,.5)+1))),1),range(2,1000))))
)
The stripped out spaces that make it less readable are cheating, of course, but then it would be even LONGER!↩︎