How can I get around declaring an unused variable in a list comprehension?
Question:
If I have a list comprehension (for example) like this:
['' for x in myList]
Effectively making a new list that has an empty string for every element in a list, I never use the x
. Is there a cleaner way of writing this so I don’t have to declare the unused x
variable?
Answers:
_
is a standard placeholder name for ignored members in a for-loop and tuple assignment, e.g.
['' for _ in myList]
[a+d for a, _, _, d, _ in fiveTuples]
BTW your list could be written without list comprehension (assuming you want to make a list of immutable members like strings, integers etc.).
[''] * len(myList)
No. As the Zen puts it: Special cases aren’t special enough to break the rules. The special case being loops not using the items of the thing being iterated and the rule being that there’s a “target” to unpack to.
You can, however, use _
as variable name, which is usually understood as “intentionally unused” (even PyLint etc. knows and respect this).
The generator objects don’t actually use the variables. So something like
list(('' for x in myList))
should do the trick. Note that x is not defined as a variable outside of the generator comprehension.
Comment to How can I get around declaring an unused variable in a for loop? (Ran out of comment size)
Python maintains the same reference for the object created. (irrespective of mutability),for example,
In [1]: i = 1
In [2]: j = 1
In [3]: id(i)
Out[3]: 142671248
In [4]: id(j)
Out[4]: 142671248
You, can see both i and j, refer to the same object in memory.What happens, when we change the value of one immutable variable.
In [5]: j = j+1
In [6]: id(i)
Out[6]: 142671248
In [7]: id(j)
Out[7]: 142671236
you can see j now starts to point a new location, (where 2 is stored), and i still points to location where 1 is stored.
While evaluating,
j = j+1
The value is picked from 142671248, calculated(if not already cached), and put at a new location 142671236. j is made to point to
the new location. In simpler terms a new copy made everytime an immutable variable is modified.
Mutability
Mutable objects act little different in this regard. When the value pointed by
In [16]: a = []
In [17]: b = a
In [18]: id(a)
Out[18]: 3071546412L
In [19]: id(b)
Out[19]: 3071546412L
Both a and b point to the same memory location.
In [20]: a.append(5)
Memory location pointed by a is modified.
In [21]: a
Out[21]: [5]
In [22]: b
Out[22]: [5]
In [23]: id(a)
Out[23]: 3071546412L
In [24]: id(b)
Out[24]: 3071546412L
Both a and b, still point to the same memory location. In other word, mutable variables act of the same memory location pointed by the variable, instead of making a copy of the value pointed by the variable, like in immutable variable case.
If you need to name your arguments (in case, for example, when writing mocks that don’t use certain arguments that are referenced by name), you can add this shortcut method:
def UnusedArgument(_):
pass
and then use it like this
def SomeMethod(name_should_remain):
UnusedArgument(name_should_remain)
It turns out that using dummy*
(starting word is dummy) as the variable name does the same trick as _
. _
is a known standard and it would be better to use meaningful variable names. So you can use dummy
, dummy1
, dummy_anything
. By using these variable names PyLint
won’t complain.
You can also prepend a variable name with _
if you prefer giving the variable a human readable name. For example you can use _foo
, _foo1
, _anything
and PyLint won’t complain. In a for loop, it would be like:
for _something in range(10):
do_something_else()
edit: Add example
Add the following comment after the for loop on the same line:
#pylint: disable=unused-variable
for i in range(100): #pylint: disable=unused-variable
A verbose way is:
newList = []
while len(newList) < len(mylist):
newList.append('')
You avoid declaring an used variable this way.
Also you can append both mutable and immutable objects (like dictionaries) into newList
.
Another thing for python newbies like me, ‘_’, ‘dummy’ are a bit disconcerting.
Try it, it’s simple:
# Use '_' instead of the variable
for _ in range(any_number):
do_somthing()
If I have a list comprehension (for example) like this:
['' for x in myList]
Effectively making a new list that has an empty string for every element in a list, I never use the x
. Is there a cleaner way of writing this so I don’t have to declare the unused x
variable?
_
is a standard placeholder name for ignored members in a for-loop and tuple assignment, e.g.
['' for _ in myList]
[a+d for a, _, _, d, _ in fiveTuples]
BTW your list could be written without list comprehension (assuming you want to make a list of immutable members like strings, integers etc.).
[''] * len(myList)
No. As the Zen puts it: Special cases aren’t special enough to break the rules. The special case being loops not using the items of the thing being iterated and the rule being that there’s a “target” to unpack to.
You can, however, use _
as variable name, which is usually understood as “intentionally unused” (even PyLint etc. knows and respect this).
The generator objects don’t actually use the variables. So something like
list(('' for x in myList))
should do the trick. Note that x is not defined as a variable outside of the generator comprehension.
Comment to How can I get around declaring an unused variable in a for loop? (Ran out of comment size)
Python maintains the same reference for the object created. (irrespective of mutability),for example,
In [1]: i = 1
In [2]: j = 1
In [3]: id(i)
Out[3]: 142671248
In [4]: id(j)
Out[4]: 142671248
You, can see both i and j, refer to the same object in memory.What happens, when we change the value of one immutable variable.
In [5]: j = j+1
In [6]: id(i)
Out[6]: 142671248
In [7]: id(j)
Out[7]: 142671236
you can see j now starts to point a new location, (where 2 is stored), and i still points to location where 1 is stored.
While evaluating,
j = j+1
The value is picked from 142671248, calculated(if not already cached), and put at a new location 142671236. j is made to point to
the new location. In simpler terms a new copy made everytime an immutable variable is modified.
Mutability
Mutable objects act little different in this regard. When the value pointed by
In [16]: a = []
In [17]: b = a
In [18]: id(a)
Out[18]: 3071546412L
In [19]: id(b)
Out[19]: 3071546412L
Both a and b point to the same memory location.
In [20]: a.append(5)
Memory location pointed by a is modified.
In [21]: a
Out[21]: [5]
In [22]: b
Out[22]: [5]
In [23]: id(a)
Out[23]: 3071546412L
In [24]: id(b)
Out[24]: 3071546412L
Both a and b, still point to the same memory location. In other word, mutable variables act of the same memory location pointed by the variable, instead of making a copy of the value pointed by the variable, like in immutable variable case.
If you need to name your arguments (in case, for example, when writing mocks that don’t use certain arguments that are referenced by name), you can add this shortcut method:
def UnusedArgument(_):
pass
and then use it like this
def SomeMethod(name_should_remain):
UnusedArgument(name_should_remain)
It turns out that using dummy*
(starting word is dummy) as the variable name does the same trick as _
. _
is a known standard and it would be better to use meaningful variable names. So you can use dummy
, dummy1
, dummy_anything
. By using these variable names PyLint
won’t complain.
You can also prepend a variable name with _
if you prefer giving the variable a human readable name. For example you can use _foo
, _foo1
, _anything
and PyLint won’t complain. In a for loop, it would be like:
for _something in range(10):
do_something_else()
edit: Add example
Add the following comment after the for loop on the same line:
#pylint: disable=unused-variable
for i in range(100): #pylint: disable=unused-variable
A verbose way is:
newList = []
while len(newList) < len(mylist):
newList.append('')
You avoid declaring an used variable this way.
Also you can append both mutable and immutable objects (like dictionaries) into newList
.
Another thing for python newbies like me, ‘_’, ‘dummy’ are a bit disconcerting.
Try it, it’s simple:
# Use '_' instead of the variable
for _ in range(any_number):
do_somthing()