The use of List "Comprehensions" in Python is a good use?
Yes, it’s a good use. The main idea has always been to let
the most readable and concise things - so unless
is a complex expression, which is more readable in
multiple lines, its use is recommended - the cases
simpler list-comprehensions exchange 3 or 4
lines of code for a single line with less
of 60 columns. It is very worthwhile.
Affects the
program performance (execution time, etc..)?
The difference is minimal - but if the idea is to create a list,
list-comprehension is a little faster
than create an empty list and go append -
only because the list constructor executes the iterator
of the "for" straight in native code - without a call
to ". append" for each element.
That difference is really minimal, and it won’t be felt
for lists of 10, 100 or 200 elements, or code snippets
to be executed only once.
For larger lists, in a program section that runs
constantly (for example, in a view of an application
web with several concurrent accesses), can start
to make real difference.
Already the use you make, to make the "print", really is not
most usual - usually use list-comprehension when
you want the same values. But when we are in interactive mode
(whether on ipython, a notebook, or pdb) this syntax can be a good shortcut
to see the content of various things - and there are no contraindications.
Even if it was a list of a few tens of thousands of "None" elements,
the difference in performance/memory consumption for a single sequential execution
is negligible, when we compare the size of this structure with the whole process
from the Python app, which includes cpython Runtime: it won’t tickle
Despite this, it is important to keep in mind that a building very similar to
the list-comprehensions, the "Generator Expressions", work much more rationally in this sense - it’s the same thing, but without being delimited by [
and ]
, and yes, only by parentheses (and sometimes even with nothing, if the context allows).
The Generator Expressions only advance one step in their "for" when an element is going to be "consumed" by a structure outside of them- and they don’t store the element - so there is no "spent" memory.
Only a Generator Expression alone doesn’t run either - someone has to "consume" its content.
That is to say:
(print(x) for x in range(11) if x % 2 == 0)
does nothing: Python prepares the object, ready
to create the values of x and call "print", but while
one for
or another function to which you pass this
Generator Expression as a parameter does not consume the values,
the for
never advances and print does not run. (The "next" function advances a Generator of 1 in 1 if someone chooses to do what the for
manually makes)
For example, the function any
waits for an eternity, and she consumes
all values until you reach the first one that is not equivalent
a boolean "False". Since "print" returns "None", it would consume
this until the end:
any(print(x) for x in range(11) if x % 2 == 0)
(also understand that if there is no ambiguity, there is no need
by a pair of parentheses exclusive to Generator Expression, as mentioned above).
A more common usage pattern is instead to put the print inside
of the repeating structure, maintain the repeating structure only generating
the desired values, and pass it as a parameter to the method join
of a string, which already takes care of formatting.
The only detail is that each element of an iterator that "Join" consumes
has to be a string.
But, in short, this is considered "good quality" for
be in production code (although this is a little subjective):
print(", ".join(str(x) for x in range(11) if not x % 2))
And just to keep the answer complete, it’s important to remember that
there are the "Dict comprehension": {chave: valor for chave, valor in iteravel}
and the "set comprehensions": {elemento for elemento in iteravel}
-
the same ideas apply to both.
If it is only to print, not worth it, because you will be creating a list for nothing, not to mention I think gambiarra: https://answall.com/a/459289/112052 - Now you need to create a list with the values, ai the difference probably will be small, but performance is something that has to be analyzed on a case-by-case basis. https://stackoverflow.com/q/22108488
– hkotsubo
For these questions, you helped me!!
– Gui Reis
You can do it in a row without having to generate a list
for x in range(11): print(x) if x % 2 == 0 else None
but it is a gambiarra because it is a crooked use of conditional expression– Augusto Vasques