Is "*_" an acceptable way to ignore arguments in Python?
Question:
If I have a function/method that is an implementation of a callback for some framework, and do not care for any further arguments, it seems to be syntactically correct, and to not have pylint/IDE complaints to use *_
to express no interest in any further arguments. The point I think is to express intent to both the tools, and other developers that these arguments are not currently relevant.
To clarify what I mean:
def my_callbacK_handler(a, b, *_):
...
I’ve not seen this idiom used in the wild – is it common, are there examples and are there known problems with this?
For those not familiar: _
expresses the intent that I am not interested in that symbol – it is the Python "dummy" that is recognized by IDE’s and linters.
Answers:
_
is just a variable like any other, but by convention it means
that you don’t intend to use that value, just declare and forget it.
[OrderedSet() for _ in xrange(n)]
builds a list of n
empty ordered sets. _
is the index, but is unused; _
is commonly used as required, but unused, variable name (not only in Python).
This is just a tricky Python idiom because there is no built-in syntax to do this.
It’s not uncommon to see this in other languages (where _
is a valid identifier). _
often
means a variable one’s not interested in the value of, but which is
needed for syntactic reasons.
Note that _(...)
as a macro call has another conventional meaning, which
comes from gettext, where one uses _("string literal")
to indicate a
string that needs localization.
A thread to read from ActivesState
I can not say about any problems, Python doesn’t use it internally, it’s just a variable, it is us who have to be careful.
Regarding the syntax of * and **: The names *args
and **kwargs
are only by convention, but there’s no need not to use them.
def my_callbacK_handler(a, b, *_):
...
So what I understand if I see this function in your code by _
idiom, that this function only uses a
and b
arguments in its working and will ignore others.
As you state: "*_
to express no interest in any further arguments".
*_
means multiple placeholders,just like you write def my_callbacK_handler(a, b, _,_,_....,_):
and will create a variable named _
which is a list of the extra arguments
It has two advantage:
- It can handle the case where there is no extra argument
def f():
return 1,2,3
def g():
return 1,2
def h():
return 1,2,3,4
_
as a placeholder can only deal with exactly one value
x,y,_ = g() # ValueError: not enough values to unpack (expected 3, got 2)
x,y,_ = h() # ValueError: too many values to unpack (expected 3)
whereas *_
can deal with any amount of values
x,y,*_ = g()
print(_)
[]
x,y,*_ = h()
print(_)
[3, 4]
One word: Prefer *_
for more robust code.
Let me just add an example:
>>> *_, a = [1,2,3]
>>> _, a
([1, 2], 3)
>>> _, a = [1,2,3]
Traceback (most recent call last):
File "<console>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
I belive that using _ as a "don’t care" variable name originates with Prolog.
In Prolog it not only means that you don’t care but it has a different semantics from other variables in that normally two instances of the same variable (eg Dummy) must match the same value, whereas two instances of _ can match different values.
I was surprised to see it being used in Python and confused when I first saw it. But it does make sense, and therefore so does *_ . Now I use it myself.
BTW It seems that _ does have a special semantics in Python as well but only in the context of it being used in the top level of the Python shell (I think), where
_ gets automatically assigned the value of the last returned function value.
If I have a function/method that is an implementation of a callback for some framework, and do not care for any further arguments, it seems to be syntactically correct, and to not have pylint/IDE complaints to use *_
to express no interest in any further arguments. The point I think is to express intent to both the tools, and other developers that these arguments are not currently relevant.
To clarify what I mean:
def my_callbacK_handler(a, b, *_):
...
I’ve not seen this idiom used in the wild – is it common, are there examples and are there known problems with this?
For those not familiar: _
expresses the intent that I am not interested in that symbol – it is the Python "dummy" that is recognized by IDE’s and linters.
_
is just a variable like any other, but by convention it means
that you don’t intend to use that value, just declare and forget it.
[OrderedSet() for _ in xrange(n)]
builds a list of n
empty ordered sets. _
is the index, but is unused; _
is commonly used as required, but unused, variable name (not only in Python).
This is just a tricky Python idiom because there is no built-in syntax to do this.
It’s not uncommon to see this in other languages (where _
is a valid identifier). _
often
means a variable one’s not interested in the value of, but which is
needed for syntactic reasons.
Note that _(...)
as a macro call has another conventional meaning, which
comes from gettext, where one uses _("string literal")
to indicate a
string that needs localization.
A thread to read from ActivesState
I can not say about any problems, Python doesn’t use it internally, it’s just a variable, it is us who have to be careful.
Regarding the syntax of * and **: The names *args
and **kwargs
are only by convention, but there’s no need not to use them.
def my_callbacK_handler(a, b, *_):
...
So what I understand if I see this function in your code by _
idiom, that this function only uses a
and b
arguments in its working and will ignore others.
As you state: "*_
to express no interest in any further arguments".
*_
means multiple placeholders,just like you write def my_callbacK_handler(a, b, _,_,_....,_):
and will create a variable named _
which is a list of the extra arguments
It has two advantage:
- It can handle the case where there is no extra argument
def f():
return 1,2,3
def g():
return 1,2
def h():
return 1,2,3,4
_
as a placeholder can only deal with exactly one value
x,y,_ = g() # ValueError: not enough values to unpack (expected 3, got 2)
x,y,_ = h() # ValueError: too many values to unpack (expected 3)
whereas *_
can deal with any amount of values
x,y,*_ = g()
print(_)
[]
x,y,*_ = h()
print(_)
[3, 4]
One word: Prefer *_
for more robust code.
Let me just add an example:
>>> *_, a = [1,2,3]
>>> _, a
([1, 2], 3)
>>> _, a = [1,2,3]
Traceback (most recent call last):
File "<console>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
I belive that using _ as a "don’t care" variable name originates with Prolog.
In Prolog it not only means that you don’t care but it has a different semantics from other variables in that normally two instances of the same variable (eg Dummy) must match the same value, whereas two instances of _ can match different values.
I was surprised to see it being used in Python and confused when I first saw it. But it does make sense, and therefore so does *_ . Now I use it myself.
BTW It seems that _ does have a special semantics in Python as well but only in the context of it being used in the top level of the Python shell (I think), where
_ gets automatically assigned the value of the last returned function value.