17

Normally in Python, one should use an _ to indicate an argument is unused.

def example_basic(unused):
   pass

becomes

def example_basic(_):
   pass

Then if there are multiple unused arguments, multiple _s can't be used since they will conflict, so a *_ is used:

def example_multiple(unused1, unused2):
   pass

becomes

def example_multiple(*_):
   pass

Finally, what should be done if there are multiple non-adjacent arguments that go unused?

def example_non_adjacent(unused1, used, unused2):
    return used

Using multiple _s still does not work, and using *_ won't work since they're non-adjacent.

Note that I would very much prefer to change the API, but for the sake of this question let's assume that's not possible. Is there a way to indicate it's ignored without using something like # pylint: disable=unused-argument for PyLint or i-dont-know-what for PyCharm?

EDIT:

I posted an example where this is needed here

TinyTheBrontosaurus
  • 4,010
  • 6
  • 21
  • 34
  • 4
    Why do you want to have an argument in function definition which is unused ? – dnit13 Nov 01 '17 at 16:22
  • 2
    from polymorphism or otherwise using a framework. we're hitting it now with django rest framework, though I'm pretty sure we can work around it. That said, I've always been curious about if there is a right way to do it. – TinyTheBrontosaurus Nov 01 '17 at 16:24
  • 1
    The right way to do it is `def func(*args, **kwargs)` – dnit13 Nov 01 '17 at 16:30
  • 4
    `_` is mostly used when you get a return value from somewhere and you have no use of that value. Not in function definitions. – dnit13 Nov 01 '17 at 16:31
  • 1
    ... and for function results, you can reuse `_` (or any other name) as often as you like: `_, _, x, _, y = function_with_many_results()` – tobias_k Nov 01 '17 at 16:33
  • 5
    I'd just name the argument after whatever it's supposed to be. For example, if it's supposed to be a connection, call it `connection`, even if you're not actually doing anything with the connection. – user2357112 Nov 01 '17 at 16:37
  • That's how it started. But then we have to put `# pylint: disable=unused-argument` above the line – TinyTheBrontosaurus Nov 01 '17 at 16:38
  • 3
    `def example_basic(_):` just looks wrong to me. Please don't do that! – PM 2Ring Nov 01 '17 at 16:39
  • I think this question is asking for opinions, and opinionated questions are off topic here. – Bryan Oakley Nov 01 '17 at 18:43
  • i disagree. I think it's a yes or no. Is there a standard way in Python to do this or not? For single unused arguments, the standard is `_`. For multiple unused arguments, the standard is TBD. By 'standard' i mean to be compatible with PyLint and/or PyCharm, which I assumed (possibly incorrectly) lined up with PEP – TinyTheBrontosaurus Nov 01 '17 at 18:54

4 Answers4

10

I've seen codes using the following idiom;

def example_non_adjacent(_0, used, _1, _2, _3, also_used):
    ...

which I find nice if you truly have lots of unused variables.

That said, just because a variable is unused does not mean that the code is more readable if you leave out its proper name. This should only be done if you really think that hiding the variable names improve the readability and/or understanding of the code.

jmd_dk
  • 12,125
  • 9
  • 63
  • 94
3

Pylint (and most likely other readers of your code) will be as happy if you concatenate several underscores. Pylint won't complain about unused arguments if you do this:

def example_non_adjacent(_, used, __):
    return used

I agree with some commenters in which this is ugly and I would try to avoid it by all means.

Pylint (and most human readers, I guess) won't complain either if you add the prefix cb_ to your function names to convey the fact that they are callbacks and you have to receive some arguments even if you do not want to use them. This looks like a better solution to me.

def cb_example_non_adjacent(unused1, used, unused2):
    return used
Stop harming Monica
  • 12,141
  • 1
  • 36
  • 56
  • Duplicate argument names in function definitions are syntax errors. It does not run at all. `cb_example_non_adjacent(unused1, used, unused1)` – Elis Byberi Nov 13 '17 at 22:34
3

Just del them. It is lightning fast because of the way garbage collector works.

def test(test):
    del test

    print('I do not need test parameter here!')

If you are passing parameters with callback method then give them a proper name and del them. Do not denote them as unused.

This is an example callback function:

def handle(socket, address):
    del address  # del is as efficient as a newline ;-)

    stream = bytes()
    while True:
        chunk = socket.recv()
        if not chunk:
            break

        stream += chunk

    return stream

Pythonistas normally do not use _ underscore name for an argument is any case possible.
You may have misunderstood usage of _ underscore as a name for a non useful variable.

It is understandable to use _ for a variable name when we do not know how to call it and/or it will not get used:

# ignore variables when unpacking a tuple
def test():
    """some code here"""

    top = 10
    right = 10
    bottom = 40
    left = 10

    return top, right, bottom, left


# here we ignore right and left
top, _, bottom, _ = test()

# use top and bottom in your code
Elis Byberi
  • 1,422
  • 1
  • 11
  • 20
-1

I strongly agree with @jmd_dk on this one. Just because the function doesn't actually reference or modify an argument, it doesn't mean it isn't 'used'. After all, it has to be instantiated and explicitly passed to the function. The only justified use of underscores for variable names is when using for-loops and list comprehensions:

numbers = {_ for _ in range(10)}

for _ in numbers:
    print("Foo!")

But the fact that you need a solution like this means there's a design problem in your code.

Daniel
  • 769
  • 8
  • 21
  • 1
    or it means there's a design problem in a framework i'm using :-) – TinyTheBrontosaurus Nov 01 '17 at 19:08
  • 3
    Actually, even in your set comprehension I would prefer to replace `_` with something like `number`, as the `_` is actually re-referenced right there in the comprehension. – jmd_dk Nov 01 '17 at 19:08
  • @TinyTheBrontosaurus Would you mind providing the actual code? I find it hard to imagine the problem's in the framework. – Daniel Nov 01 '17 at 19:24
  • if i do that i'll make it a separate question. I'll let you know if/when I do. – TinyTheBrontosaurus Nov 01 '17 at 21:27
  • 2
    @Coal_ The meaning of "unused" in pylint warnings is exactly that: the parameter is neither being referenced nor assigned. You might disagree and not use "unused" to express that, but the problem would remain the same: pylint complaining. – Stop harming Monica Nov 01 '17 at 21:46
  • @Goyo You can only satisfy pylint to a certain extent. Even PEP8 says -rules are there to be broken- – Daniel Nov 01 '17 at 22:00
  • @Coal_ Well the question seems to be about satisfying pylint and in this case it can be done. The even have an answer in their FAQ about unused arguments in callbacks, which is where I expect this problem to arise. – Stop harming Monica Nov 01 '17 at 22:54
  • 2
    @Coal_ Besides, unused arguments could be an overlook, that's why you usually want code analysis tools to warn you about them. But not when some framework forces you to have unused arguments. It is not just about making pylint happy but about making it helpful without annoying you. – Stop harming Monica Nov 01 '17 at 23:00
  • @Coal_, I just posted an example that needs it in https://stackoverflow.com/questions/47316154/how-to-remove-unused-function-parameters-in-shutil-rmtree. It's not the exact same issue I hit, but it's similar – TinyTheBrontosaurus Nov 15 '17 at 19:56