390

Say I have a Python function that returns multiple values in a tuple:

def func():
    return 1, 2

Is there a nice way to ignore one of the results rather than just assigning to a temporary variable? Say if I was only interested in the first value, is there a better way than this:

x, temp = func()
Mat
  • 82,161
  • 34
  • 89
  • 109
  • 3
    I got curious of this too coming from Matlab's similar notion of [Ignore Function Outputs](https://www.mathworks.com/help/matlab/matlab_prog/ignore-function-outputs.html) where they use `~` as the syntax to ignore a particular return variable – jxramos Jun 12 '17 at 18:09
  • 5
    You selected the wrong answer as solution – AGP Jan 07 '19 at 17:58

12 Answers12

752

You can use x = func()[0] to return the first value, x = func()[1] to return the second, and so on.

If you want to get multiple values at a time, use something like x, y = func()[2:4].

endolith
  • 25,479
  • 34
  • 128
  • 192
Luke Woodward
  • 63,336
  • 16
  • 89
  • 104
  • 108
    This should be the accepted answer. You can also use things like `func()[2:4]` if you only want *some* of the return values. – endolith Aug 04 '11 at 02:03
  • This sucks because you have to call func() multiple times. It's a waste of CPU time – Tyler Liu Aug 13 '11 at 10:43
  • 14
    It doesn't call the function multiple times: >>> def test(): ... print "here" ... return 1,2,3 ... >>> a,b = test()[:2] here [edit: sorry that code didn't come through, aparently you only get one line in comments. For those not familiar >>> and ... are the start of a new line in the python shell] – teeks99 Aug 17 '11 at 20:56
  • 1
    @TylerLong: No you don't. If you want more than one value at a time, use something like `x, y = func()[0:1]` – endolith Mar 26 '13 at 14:22
  • @endolith it makes some sense but it is not a general solution. Suppose that func() returns 100 values and I want the 13th, 25th, 58th, 89th and 98th, then I still have to call func() multiple times. – Tyler Liu Mar 26 '13 at 15:06
  • 49
    @TylerLong: I think `_, _, _, _, _, _, _, _, _, _, _, _, _, a, _, _, _, _, _, _, _, _, _, _, _, b, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, c, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, d, _, _, _, _, _, _, _, _, e, _ = func()` is less clear than calling the function multiple times, but that's just my opinion. If your function returns that many items, I think using numpy would be preferable: `a, b, c, d, e = func()[[13, 25, 58, 89, 98]]` – endolith Mar 26 '13 at 15:41
  • 35
    @endolith I think this is better and does not need numpy and does not need to call func() multiple times: `result = func()` `a = result[13]` `b = result[25]` ... – Tyler Liu Mar 27 '13 at 03:04
  • How do I use this syntax with an `in` statement such as when I would use `for (_, _, x, _) in something():` ? – Zitrax Nov 08 '13 at 10:30
  • @Zitrax: the only real way to use this syntax in the way you describe would be to introduce a variable for the values returned by `something()`, i.e. `for spam in something():` followed by `x = spam[2]`. – Luke Woodward Nov 08 '13 at 19:10
  • 1
    @Zitrax don't forget you can always save the return value and reuse it: `result=something()` and then `result[2]` and so on.. – Eli Mar 02 '16 at 09:11
  • @endolith this obviously doesn't work when the goal is to suppress output during an interactive session from a function that returns a single value. – abcd Mar 16 '16 at 01:02
  • @dbliss I don't understand – endolith Mar 16 '16 at 18:34
  • @dbliss Ok, but that's a different question. This one is about things that return sequences. You want something like `reload(numpy);` to suppress IPython's output: http://stackoverflow.com/q/23692950/125507 – endolith Mar 16 '16 at 21:43
  • @endolith if you are dogmatically opposed to `_`, then yes, you can use a combination of indexing and semicolons to handle unwanted output from functions. i am not so ideologically disposed, so i will continue to use the elegant, general-purpose solution `_ = . . .` i have never written a function that returns 100 values only a seemingly random subset of which i actually need. – abcd Mar 17 '16 at 00:32
  • @dbliss You're not even talking about the same thing. This question is about *assigning* only a subset of a returned object, while you're talking about suppressing IPython's *printing* of a returned object when it's not assigned. [The semicolon is what you're looking for.](https://ipython.org/ipython-doc/3/interactive/tips.html#suppress-output) – endolith Mar 17 '16 at 00:49
  • 5
    This style is not nice when you want to ignore one or a few values in between, e.g. `x, __, y = func()` – ndemou Jun 15 '16 at 13:30
  • Is there any difference between both approaches, if it comes to copying data? E.G. pre-`numpy` 1.11 `gradient` may return a list of quite big arrays. Is the copying process bypassed by `x,y = np.gradient(z)[1,2]` for the other arrays within the output list? – Renatius Jul 20 '16 at 08:39
  • 2
    This should be an excepted answer. – Josef Klimuk Mar 04 '19 at 14:48
342

One common convention is to use a "_" as a variable name for the elements of the tuple you wish to ignore. For instance:

def f():
    return 1, 2, 3

_, _, x = f()
Brian Clapper
  • 25,705
  • 7
  • 65
  • 65
  • 2
    Very interesting concept, but not very Pythonic. However, neither is my submitted solution. :-P May I ask, where did you hear of this convention? I'd like to learn how popular it is. – Evan Fosmark Jan 10 '09 at 22:21
  • That's the concept I've heard of before but couldn't remember. Not sure where I heard of it from though. – Mat Jan 10 '09 at 22:28
  • 6
    I've seen it in various pieces of code here and there. If you do a grep -w '_,' *.py in the standard Python library, you'll find a few instances of it. For example, UserDict.py has a couple instances of it. I've also seen it in packages like Pygments and Django. – Brian Clapper Jan 10 '09 at 22:30
  • 3
    @Evan I actually find this to be very Pythonic, especially given python's propensity for using underscores. (int.__mul__, __iter__, __builtins__, etc.) – brad Jan 10 '09 at 22:59
  • 1
    It's definitely standard in the python community, I've been doing it so long I don't remember why I started doing it. I was surprised I didn't find it in PEP 8. – llimllib Jan 11 '09 at 06:36
  • 105
    -1: this "convention" sucks when you add gettext functionality to someone else's code (that defines a function called '_') so it should be banned – nosklo Jan 11 '09 at 13:32
  • 41
    Good point--though it's debatable whether gettext's insistence on installing a function called "_" is a good idea. Personally, I find it a little ugly. Regardless, the use of "_" as a throwaway variable is widespread. – Brian Clapper Jan 11 '09 at 13:44
  • 4
    This convention is also common in Haskell. Anyone know where it originated? – Kiv Jan 11 '09 at 19:07
  • This is neat. Seems to me that it comes from the Perl world. – Camilo Díaz Repka Jan 11 '09 at 21:19
  • 3
    The origin, as far as I can tell, is ML. This is supported by the same usage in functional languages, especially ML-derived/-inspired languages such as OCaml, F#, Nemerle, etc. – Serafina Brocious Jan 19 '09 at 10:14
  • 35
    -1: _ means "last output" in IPython. I would never assign something to it. – endolith Jan 24 '10 at 17:27
  • 2
    @Draemon: http://ipython.scipy.org/doc/manual/html/interactive/tutorial.html#use-the-output-cache – endolith Jun 13 '10 at 04:43
  • 26
    Ok, I didn't notice the "I" - thanks for the reference. IMHO you can't expect others not to use a variable just because one Python app defines its own magical use for it. – Draemon Jun 13 '10 at 23:38
  • 10
    some IDEs such as PyDev will give you a warning on this, because you have unused variables. – teeks99 Aug 17 '11 at 20:58
  • 3
    @Draemon: There are two examples so far of the underscore having other purposes. It's not a throwaway variable and should not be treated as one. The function outputs a tuple; use it like a tuple. – endolith Mar 26 '13 at 14:34
  • 3
    @endolith that's the point. python already assigns to `_`. explicitly assigning to `_` is equivalent to assigning to nothing, which is the goal. (i.e., normally both `_` and a new variable are assigned to -- this leaves out the new variable.) – abcd Mar 16 '16 at 00:57
  • 4
    @nosklo sure, any Python convention that fails to be consistent with non-Python software should be banned. hell, while we're at it, let's just ban Python. maybe the people who wrote `gettext` can recommend something else. – abcd Mar 16 '16 at 01:04
  • 2
    Regardless of which specific module wants to use `_` why should one use any name and totally discard it, when the name could be used by something else? Why not just do `x, print = func()` for example? `func()[0]` is clearly much better, truly discards the parts of the tuple not needed and doesn't pollute the namespace. – Petruza Feb 10 '19 at 18:40
  • 2
    Another disadvantage of assigning to `_` (or to any variable name) is that the reference associated with that name will then persist until the end of the current function, or until you explicitly `del _`. But since the objected is unwanted, it will usually make more sense for it to be garbage-collected ASAP. – jez Nov 12 '19 at 21:31
  • All the naysayers here talking about `_` already being used, not realizing you can just use two underscores `__`... – wjandrea Sep 20 '21 at 21:18
144

If you're using Python 3, you can you use the star before a variable (on the left side of an assignment) to have it be a list in unpacking.

# Example 1: a is 1 and b is [2, 3]

a, *b = [1, 2, 3]

# Example 2: a is 1, b is [2, 3], and c is 4

a, *b, c = [1, 2, 3, 4]

# Example 3: b is [1, 2] and c is 3

*b, c = [1, 2, 3]       

# Example 4: a is 1 and b is []

a, *b = [1]
Joe
  • 46,419
  • 33
  • 155
  • 245
  • 32
    You can also use `a, *_ = f()` to ignore arbitrary number of returned values after `a`. – THN May 10 '20 at 09:53
29

The common practice is to use the dummy variable _ (single underscore), as many have indicated here before.

However, to avoid collisions with other uses of that variable name (see this response) it might be a better practice to use __ (double underscore) instead as a throwaway variable, as pointed by ncoghlan. E.g.:

x, __ = func()
Community
  • 1
  • 1
lackadaisical
  • 1,628
  • 18
  • 21
  • 5
    Not a bad idea at all. But then '_ _ ' would declare a variable in the namespace. Whereas, ' _ ' does not declare unless specifically used on the left hand side of the assignment statement like above (eg: `a, _, _ = 1,8,9`). Until that point, it stores the result of the last statement executed which if you want to catch, you'd normally use a variable to store that value. And this is why, ' _ ' is the suggested variable name to catch junk values. ' _ ' values get overwritten soon after another statement is executed. In case of '_ _', value would remain there until GC cleans it off. – Archit Feb 11 '20 at 18:49
23

Remember, when you return more than one item, you're really returning a tuple. So you can do things like this:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2
endolith
  • 25,479
  • 34
  • 128
  • 192
Evan Fosmark
  • 98,895
  • 36
  • 105
  • 117
  • Useful for the syntax. A problem with this is that it requires calling the function multiple times. For such a trivial function, this is no big deal. But, in more complex functions, this could be undesirable. Good to know there are many approaches.... – jvriesem Aug 19 '21 at 18:45
22

The best solution probably is to name things instead of returning meaningless tuples (unless there is some logic behind the order of the returned items). You can for example use a dictionary:

def func():
    return {'lat': 1, 'lng': 2}
    
latitude = func()['lat']

You could even use namedtuple if you want to add extra information about what you are returning (it's not just a dictionary, it's a pair of coordinates):

from collections import namedtuple 

Coordinates = namedtuple('Coordinates', ['lat', 'lng'])

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

If the objects within your dictionary/tuple are strongly tied together then it may be a good idea to even define a class for it. That way you'll also be able to define more complex operations. A natural question that follows is: When should I be using classes in Python?

Most recent versions of python (≥ 3.7) have dataclasses which you can use to define classes with very few lines of code:

from dataclasses import dataclass

@dataclass
class Coordinates:
    lat: float = 0
    lng: float = 0

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

The primary advantage of dataclasses over namedtuple is that its easier to extend, but there are other differences. Note that by default, dataclasses are mutable, but you can use @dataclass(frozen=True) instead of @dataclass to force them being immutable.

Here is a video that might help you pick the right data class for your use case. And a another video on attrs vs. dataclass that enlight some interesting details about why attrs might be interesting.

cglacet
  • 8,873
  • 4
  • 45
  • 60
  • 2
    This is the only answer that gets at the heart of the problem hidden in this question. If you are trying to select one of a function's tuple outputs, they probably shouldn't be in a tuple. Tuples are for things that "go together" in an ordered way. In the OP's case, they are (probably) "qualitatively different" outputs, and should really be named in some way. Asking a reader to understand what the first and second output refer to, when there's no natural ordering, is a recipe for trouble. – Sanjay Manohar Sep 22 '21 at 21:54
19

Three simple choices.

Obvious

x, _ = func()

x, junk = func()

Hideous

x = func()[0]

And there are ways to do this with a decorator.

def val0( aFunc ):
    def pick0( *args, **kw ):
        return aFunc(*args,**kw)[0]
    return pick0

func0= val0(func)
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 6
    I really prefer the `_` variable. It's very obvious that you're ignoring a value – Claudiu Nov 23 '09 at 18:22
  • 26
    Your examples are backwards. `x, _ = func()` is hideous, and `x = func()[0]` is obvious. Assigning to a variable and then not using it? The function is returning a tuple; index it like a tuple. – endolith Mar 26 '13 at 14:41
  • 9
    In pattern matching languages, from which Python derived this pattern, the 'obvious' method is indeed obvious, not hideous, and canonical. Although, in such languages the wildcard is a supported language feature whereas in Python it's a real variable and gets bound, which is a little unpalatable. – Joe Nov 29 '13 at 14:21
  • 5
    For list processing languages, from which Python is derived `;)`, list accessors such as `a[0]`, `a[:]` (list copy), `a[::2]` (every two elements), and `a[i:] + a[:i]` (rotate a list), are indeed, also obvious and canonical. – cod3monk3y Nov 27 '14 at 16:40
5

This is not a direct answer to the question. Rather it answers this question: "How do I choose a specific function output from many possible options?".

If you are able to write the function (ie, it is not in a library you cannot modify), then add an input argument that indicates what you want out of the function. Make it a named argument with a default value so in the "common case" you don't even have to specify it.

    def fancy_function( arg1, arg2, return_type=1 ):
        ret_val = None
        if( 1 == return_type ):
            ret_val = arg1 + arg2
        elif( 2 == return_type ):
            ret_val = [ arg1, arg2, arg1 * arg2 ]
        else:
            ret_val = ( arg1, arg2, arg1 + arg2, arg1 * arg2 ) 
        return( ret_val )

This method gives the function "advanced warning" regarding the desired output. Consequently it can skip unneeded processing and only do the work necessary to get your desired output. Also because Python does dynamic typing, the return type can change. Notice how the example returns a scalar, a list or a tuple... whatever you like!

1-ijk
  • 311
  • 3
  • 4
5

This seems like the best choice to me:

val1, val2, ignored1, ignored2 = some_function()

It's not cryptic or ugly (like the func()[index] method), and clearly states your purpose.

klozovin
  • 2,363
  • 2
  • 22
  • 30
5

If this is a function that you use all the time but always discard the second argument, I would argue that it is less messy to create an alias for the function without the second return value using lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 
Chrigi
  • 520
  • 5
  • 11
3

When you have many output from a function and you don't want to call it multiple times, I think the clearest way for selecting the results would be :

results = fct()
a,b = [results[i] for i in list_of_index]

As a minimum working example, also demonstrating that the function is called only once :

def fct(a):
    b=a*2
    c=a+2
    d=a+b
    e=b*2
    f=a*a
    print("fct called")
    return[a,b,c,d,e,f]

results=fct(3)
> fct called

x,y = [results[i] for i in [1,4]]

And the values are as expected :

results
> [3,6,5,9,12,9]
x
> 6
y
> 12

For convenience, Python list indexes can also be used :

x,y = [results[i] for i in [0,-2]]

Returns : a = 3 and b = 12

jeannej
  • 1,135
  • 1
  • 9
  • 23
0

It is possible to ignore every variable except the first with less syntax if you like. If we take your example,


# The function you are calling.
def func():
    return 1, 2

# You seem to only be interested in the first output.
x, temp = func()

I have found the following to works,

x, *_ = func()

This approach "unpacks" with * all other variables into a "throwaway" variable _. This has the benefit of assigning the one variable you want and ignoring all variables behind it.

However, in many cases you may want an output that is not the first output of the function. In these cases, it is probably best to indicate this by using the func()[i] where i is the index location of the output you desire. In your case,

# i == 0 because of zero-index.
x = func()[0]

As a side note, if you want to get fancy in Python 3, you could do something like this,

# This works the other way around.
*_, y = func()

Your function only outputs two potential variables, so this does not look too powerful until you have a case like this,

def func():
    return 1, 2, 3, 4

# I only want the first and last.
x, *_, d = func()
Jesse H.
  • 465
  • 4
  • 12