Well, you could do...

first,second = foo(True) or (None,None)
first,second = foo(False) or (None,None)

but as far as I know there's no simpler way to expand None to fill in the entirety of a tuple.

Answer from Amber on Stack Overflow
🌐
Reddit
reddit.com › r/python › is there a way to annotate the return types of a function that returns multiple values
r/Python on Reddit: Is there a way to annotate the return types of a function that returns multiple values
August 31, 2022 - I guess an example where none makes sense is the dictionary .get method where you want to be able to provide a default and you don't want an exception ... 3.8 3.10 it should be equivalent, using Union[int,str] was the old way (like using List instead of list) ... You can have multiple return statements and all of them can be of the same type. Union is used to say that your return can be of more than one type. ... What kind of values? You could use a tuple or a list(if they're all the same type of value) or something like that.
🌐
Stanford
web.stanford.edu › class › archive › cs › cs106a › cs106a.1202 › handouts › py-tuple.html
Stanford
But sometimes it really makes sense to return 2 or more values. The Pythonic way to do this is to return a tuple packing together the values. Like this · def min2(a, b): """ Given 2 ints, returns (True, min_val) if at least one is negative and min_val is the minimum value.
🌐
Real Python
realpython.com › python-type-hints-multiple-types
How to Use Type Hints for Multiple Return Types in Python – Real Python
March 8, 2024 - Then, a pipe operator (|) followed by None indicates that the return value could be either a two-string tuple or None, depending on the input value. To implement the same function in Python earlier than 3.10, use the Tuple and Union types from ...
🌐
freeCodeCamp
freecodecamp.org › news › python-returns-multiple-values-how-to-return-a-tuple-list-dictionary
Python Return Multiple Values – How to Return a Tuple, List, or Dictionary
July 20, 2020 - Here’s an example of a function that uses parentheses () to return a tuple. def person(name, age): return (name, age) print(person("henry", 5)) #result: ('henry', 5) A list is an ordered, mutable sequence.
🌐
Real Python
realpython.com › python-return-statement
The Python return Statement: Usage and Best Practices – Real Python
June 14, 2024 - You can then unpack the tuple into separate variables or store it as a single variable. What are the best practices I should apply when using the return statement?Show/Hide · First, explicitly return None when appropriate.
🌐
Pierian Training
pieriantraining.com › home › how to return tuple in python
How to Return Tuple in Python - Pierian Training
June 18, 2023 - They are similar to lists, but the key difference is that tuples cannot be modified once they are created. Tuples can be returned from functions just like any other data type in Python.
🌐
GitHub
github.com › fastapi › typer › issues › 410
Empty tuple returned for Option instead of expected `None` when no values passed · Issue #410 · fastapi/typer
March 17, 2022 - import typer from typing import Optional, List app = typer.Typer(add_completion=False) @app.command() def main( foos: Optional[tuple[str]] = typer.Option(None, "--foo"), bar: Optional[str] = typer.Option(None, "--bar"), ): print(f"{type(foos)=}, {foos=}") print(f"{type(bar)=}, {bar=}") if __name__ == "__main__": app()
Published   Jul 03, 2022
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › getting a nonetype not iterable error when trying to return a tuple of values from a function.... but i can't find the nonetype
r/learnpython on Reddit: Getting a NoneType not iterable Error when trying to return a tuple of values from a function.... But I can't find the NoneType
July 19, 2014 -

This is function that uses beautiful soup to find the <a> tag which contains the URI segment that needs to be appended onto the base URI.

def get_next_page(soup, page):
    next = page+1
    anchors = soup.find_all('a', {'href':True})    
    for each in anchors:
        suffix = each['href'].strip()
        l = len(suffix)
        try:
            next_check = int(suffix[l:l+1])
        except ValueError:
            next_check = 0
        if next_check == next:
            return (suffix, next_check)

I call it with this: next_page, page = get_next_page(soup, page)

Initially I was having problems trying to determine if the href value I was looking for (after being sliced) was equal to the counter-page number variable (which is just page ). To remedy this I used try: x = int(y) Except ValueError: x= 0.

As you can see through, when that test is successful, it returns the full href value (which has to be something because I use {'href':True} in my .find_all parameters. The other part of the tuple being returned is next_check ...which equals next... and next is just a counter that should be a value of 2 when this function runs for the first time. [In another function I start with page = 1 then I call the function above with page. page is incremented and assigned to a different variable (next), and ultimately returned... so that too should have a value. In other words, I cannot see where either one of the tuple values being returned is None.

🌐
Python.org
discuss.python.org › ideas
Implicit tuple return type - Ideas - Discussions on Python.org
May 8, 2024 - Before: def go() -> tuple[int, str]: return 1, "A" After: def go() -> int, str: return 2, "B" I don’t know what else to say and I think it just looks good :slight_smile:
🌐
Quora
quora.com › Is-returning-multiple-variables-in-Python-considered-poor-programming
Is returning multiple variables in Python considered 'poor' programming? - Quora
Answer (1 of 6): Nope; it is good programming. This question can be paraphrased as “Is returning a tuple in Python considered ‘poor’ programming?”, because that is exactly what those multiple values are - a tuple. Returning any data type cannot be considered bad practice.
🌐
Quantifiedcode
docs.quantifiedcode.com › python-anti-patterns › readability › not_using_named_tuples_when_returning_more_than_one_value.html
Not using named tuples when returning more than one value from a function — Python Anti-Patterns documentation
Named tuples can be used anywhere where normal tuples are acceptable, but their values can be accessed through their names in addition to their indexes. This makes the code more verbose and readable. The code below returns a first name, middle name, and last name using a normal, unnamed tuple.
🌐
Stanford CS
cs.stanford.edu › people › nick › py › python-tuple.html
Python Tuples
But sometimes it really makes sense to return 2 or more values. The Pythonic way to do this is to return a tuple packing together the values. Like this · def min2(a, b): """ Given 2 ints, returns (True, min_val) if at least one is negative and min_val is the minimum value.
Top answer
1 of 2
19

I think the choices need to be considered strictly from the caller's point of view: what is the consumer most likely to need to do?

And what are the salient features of each collection?

  • The tuple is accessed in order and immutable
  • The list is accessed in order and mutable
  • The dict is accessed by key

The list and tuple are equivalent for access, but the list is mutable. Well, that doesn't matter to me the caller if I'm going to immediately unpack the results:

score, top_player = play_round(players)
# or
idx, record = find_longest(records)

There's no reason here for me to care if it's a list or a tuple, and the tuple is simpler on both sides.

On the other hand, if the returned collection is going to be kept whole and used as a collection:

points = calculate_vertices(shape)
points.append(another_point)
# Make a new shape

then it might make sense for the return to be mutable. Homogeneity is also an important factor here. Say you've written a function to search a sequence for repeated patterns. The information I get back is the index in the sequence of the first instance of the pattern, the number of repeats, and the pattern itself. Those aren't the same kinds of thing. Even though I might keep the pieces together, there's no reason that I would want to mutate the collection. This is not a list.

Now for the dictionary.

the last one creates more readable code because you have named outputs

Yes, having keys for the fields makes heterogenous data more explicit, but it also comes with some encumbrance. Again, for the case of "I'm just going to unpack the stuff", this

round_results = play_round(players)
score, top_player = round_results["score"], round_results["top_player"]

(even if you avoid literal strings for the keys), is unnecessary busywork compared to the tuple version.

The question here is threefold: how complex is the collection, how long is the collection going to be kept together, and are we going to need to use this same kind of collection in a bunch of different places?

I'd suggest that a keyed-access return value starts making more sense than a tuple when there are more than about three members, and especially where there is nesting:

shape["transform"]["raw_matrix"][0, 1] 
# vs.
shape[2][4][0, 1]

That leads into the next question: is the collection going to leave this scope intact, somewhere away from the call that created it? Keyed access over there will absolutely help understandability.

The third question -- reuse -- points to a simple custom datatype as a fourth option that you didn't present.

Is the structure solely owned by this one function? Or are you creating the same dictionary layout in many places? Do many other parts of the program need to operate on this structure? A repeated dictionary layout should be factored out to a class. The bonus there is that you can attach behavior: maybe some of the functions operating on the data get encapsulated as methods.

A fifth good, lightweight, option is namedtuple(). This is in essence the immutable form of the dictionary return value.

2 of 2
1

Don't think about functions returning multiple arguments. Conceptually, it is best to think of functions as both receiving and returning a single argument. A function that appears to accept multiple arguments actually receives just a single argument of tuple (formally product) type. Similarly, a function that returns multiple arguments is simply returning a tuple.

In Python:

def func(a, b, c):
  return b, c

could be rewritten as

def func(my_triple):
  return (my_triple[1], my_triple[2])

to make the comparison obvious.

The first case is merely syntactic sugar for the latter; both receive a triple as an argument, but the first pattern-matches on its argument to perform automatic destructuring into its constituent components. Thus, even languages without full-on general pattern-matching admit some form of basic pattern matching on some of their types (Python admits pattern-matching on both product and record types).


To return to the question at hand: there is no single answer to your question, because it would be like asking "what should be the return type of an arbitrary function"? It depends on the function and the use case. And, incidentally, if the "multiple return values" are really independent, then they should probably be computed by separate functions.

🌐
Quora
quora.com › When-returning-multiple-values-from-a-function-why-does-Python-use-a-tuple-instead-of-a-list
When returning multiple values from a function, why does Python use a tuple instead of a list? - Quora
Answer (1 of 4): First things first, your function will never return multiple values. It will always return a single value. But in some cases, this single value is a container for multiple values. I think that when you talk about returning multiple values, you are referring to the shortcut syntax...
🌐
Python.org
discuss.python.org › ideas
An idea to allow implicit return of NamedTuples - Ideas - Discussions on Python.org
October 31, 2023 - In the current versions of Python, there is a convenient way to implicitly return a tuple using commas or a parenthesis-based syntax. For example: def fx(): return 1, 2 and def fx(): return (1, 2) Both of these examples return a tuple containing multiple values.