54

Some languages have the feature to return values using parameters also like C#. Let’s take a look at an example:

class OutClass
{
    static void OutMethod(out int age)
    {
        age = 26;
    }
    static void Main()
    {
        int value;
        OutMethod(out value);
        // value is now 26
    }
}

So is there anything similar in Python to get a value using parameter, too?

Melebius
  • 5,590
  • 3
  • 34
  • 46
Leonid
  • 21,014
  • 24
  • 65
  • 90

5 Answers5

82

Python can return a tuple of multiple items:

def func():
    return 1,2,3

a,b,c = func()

But you can also pass a mutable parameter, and return values via mutation of the object as well:

def func(a):
    a.append(1)
    a.append(2)
    a.append(3)

L=[]
func(L)
print(L)   # [1,2,3]
Mark Tolonen
  • 148,243
  • 22
  • 160
  • 229
  • 4
    Yes, this is the way to go about multiple return values in python. Returning tuples is better than trying to modify one of the given parameters – helloworld922 Jan 15 '11 at 21:36
  • 7
    I am not quite sure if saying "returning multiple values" is appropriate here. It actually returns one value which is a `tuple` that contains multiple elements. – Tarik Nov 04 '13 at 00:18
  • 30
    There is reason. For example well known 'TryDo' pattern: `if try_parse(out result): print(result)`. This code is clean. Try to use tuples here and it will become ugly. – renadeen Feb 27 '14 at 10:57
  • 1
    That's not valid Python. In Python it would be `result = parse(something)` that throws exception on error and wrapped in `try/except`. – Mark Tolonen Feb 23 '15 at 17:44
  • 4
    "There is no reason" sometimes means "I haven't thought of a reason". @renadeen that's a great point, I actually came here looking for a TryDo pattern. If-else trees would be a better way to code multiple parsing tries. Mark Tolonen, try/except would nest deeper with each try, or I haven't thought of a way that wouldn't. – Bob Stein Sep 22 '18 at 14:21
  • @Bob Put all the parses in one try, or return None and use `if result: print(result)` or the like to process individually, or return a parse class instance that holds the results and/or errors. – Mark Tolonen Sep 22 '18 at 14:50
  • @Mark we probably need less hypothetical and more code. Would love to discuss over a whiteboard on a spare afternoon. (Whatever that is, I'm free in 2050.) I suspect putting the parses in one try just complicates the try-clause, and doesn't apply if each parse requires different handling. I think you're right, a parse class is the classier way, and the way I went, though I think that code is a little more cluttered than a **multiple-output function** would be. – Bob Stein Sep 22 '18 at 16:08
  • Not working if not use .append() ```def f(a): a=[122] x=[333] f(x) x [333]``` – Nam G VU Jul 14 '19 at 05:27
  • @Nam That’s because that isn’t mutation of the original object. You’re assigning a new object. `a` has to remain a reference to the original list, and the contents modified. It doesn’t have to be append...any method the modifies the original list will do. Just don’t use assignment. – Mark Tolonen Jul 14 '19 at 06:34
  • Multiple assignments do not replace output parameters in cases where the function returns a success flag and puts the result in an output parameter. Such a function may be put inside an `if` statement, whereas in *Python* you have first to assign and then to test. Bidirectional input/output parameters are also indispensable as accumulators in functions that append strings or increment numerical values. How can one implement a normal function, rather than an object method, that appends one string to another? – Ant_222 Mar 15 '21 at 10:51
  • @Ant_222 Strings are immutable, so you must reassign: `s = ''.join(s,other)` – Mark Tolonen Mar 15 '21 at 14:55
  • Sorry for joining the discussion so late, but this helps me because I need an optional (additional) return parameter for my function and I don't see/know another way, especially without breaking the existing legacy code. – Meredith Hesketh Fortescue Nov 12 '21 at 20:14
7

You mean like passing by reference?

For Python object the default is to pass by reference. However, I don't think you can change the reference in Python (otherwise it won't affect the original object).

For example:

def addToList(theList):   # yes, the caller's list can be appended
    theList.append(3)
    theList.append(4)

def addToNewList(theList):   # no, the caller's list cannot be reassigned
    theList = list()
    theList.append(5)
    theList.append(6)

myList = list()
myList.append(1)
myList.append(2)
addToList(myList)
print(myList)   # [1, 2, 3, 4]
addToNewList(myList)
print(myList)   # [1, 2, 3, 4]
Bob Stein
  • 14,529
  • 8
  • 77
  • 98
helloworld922
  • 10,513
  • 4
  • 44
  • 83
4

Pass a list or something like that and put the return value in there.

extraneon
  • 22,900
  • 2
  • 45
  • 50
1

In addition, if you feel like reading some code, I think that pywin32 has a way to handle output parameters.

In the Windows API it's common practice to rely heavily on output parameters, so I figure they must have dealt with it in some way.

s.m.
  • 7,705
  • 2
  • 36
  • 44
1

You can do that with mutable objects, but in most cases it does not make sense because you can return multiple values (or a dictionary if you want to change a function's return value without breaking existing calls to it).

I can only think of one case where you might need it - that is threading, or more exactly, passing a value between threads.

def outer():
    class ReturnValue:
        val = None
    ret = ReturnValue()
    def t():
        # ret = 5 won't work obviously because that will set
        # the local name "ret" in the "t" function. But you
        # can change the attributes of "ret":
        ret.val = 5

    threading.Thread(target = t).start()

    # Later, you can get the return value out of "ret.val" in the outer function
AndiDog
  • 65,893
  • 20
  • 156
  • 201