On Fri, Jul 26, 2019 at 12:51:46PM -0000, Eli Berkowitz wrote:
(This is my first time posting on any Python list; I've tried to search for this idea and didn't find it but if I looked in the wrong places/this has already been discussed I apologize and feel free to tell me!)
Say you have a list and you want to perform some operation on each item in the list - but you don't need to store the result in a list.
Does that come up very often? That means you're performing the operation only for the side-effects. I can't think of many situations where that would be useful. And the few times that it does come up, there are usually better ways to get the result you want, e.g.: # Instead of this: for x in lst: L.append(x) # Use this: L.extend(lst) # Instead of this: for x in lst: print(x) # Use this: print(*lst, sep='\n')
There are three simple ways of doing this, at least as far as I know: ([print(item)] could be any expression, just using it as an example)
``` lst = [1, 2, 3, 4]
#1 for item in lst: print(item)
# 2 [print(item) for item in lst]
No no no, this is wrong and bad, because you are building a list full of Nones that has to be thrown away afterwards. But you know that.
# 3 for item in lst: print(item)
Aside from being compressed to one line instead of two, that's identical to #1. They generate the same code, and both are perfectly fine if you have some reason for wanting to save a line.
#1 - In my opinion, this should be a one line operation so #1 is not ideal.
Why should it be a one-liner? Do you have a shortage of vertical space to work with? Your comment here contradicts your comment about #3, where you say that making it a one-liner is "very unpythonic".
#2 - It also shouldn't require storing results in array, to save time/memory, so #2 is out. #3 - I think #3 is just not good syntax, it seems very unpythonic to me - it breaks the norm that blocks go on their own lines. It does seem the best of the three though and I know my assessment is kind of subjective.
You can't have #1 and #3 at the same time. If it is unpythonic to have a loop on one line, then you need to split it over two lines. Inventing new syntax just so you can have a loop on one line when the language already permits loops on one line is unnecessary.
I'm wondering if a possible alternative syntax could be a for-expression, like there's if-expressions, which always evaluates to None: ``` print(item) for item in lst ```
That clashes with the syntax for a generator comprehension. Generator comprehensions are funny beasts, because they require parentheses when they stand alone: it = expression for item in lst # Syntax error. it = (expression for item in lst) # Permitted. But when the parens are already there, as in a function call, you can (and should) leave the gen comprehension brackets out: all((expression for item in lst)) # Unnecessary extra parens. all(expression for item in lst) # Preferred. Because of that, your suggested syntax would be ambiguous: function(expression for item in lst) could mean you are calling function() with a single generator comprehension as argument, or you are evaluating a "for-expression" for its side-effects and then calling function() with None as argument.
A more practical example of when this would be useful is extending list-2 with a modified version of list-1 - this syntax would avoid creating an intermediate list (not sure if the way lists are implemented in python removes this advantage by the way it resizes lists though).
``` lst1 = [1, 2, 3] lst2 = [4, 5, 6] lst1.append(item * 2) for item in lst1 ```
lst2.extend(item*2 for item in lst1) lst2.extend(map(lambda x: 2*x, lst1) In my personal toolbox, I have this function: def do(func, iterable, **kwargs): for x in iterable: func(x, **kwargs) Which I can use like this: do(print, lst) But I hardly ever do, since most of the time there are simpler alternatives. But feel free to use it in your own code. -- Steven