user423455
user423455

Reputation: 843

python function that modifies parameters

def add(a,b):
    for i in range(len(a)):
        a[i] = a[i] + b

def main():
    amounts = [100,200]
    rate = 1
    add(amounts,rate)
    print amounts

main()

The function add does not have a return. I read that changes are available to only mutable objects like list. But why did the person omits the return? Either with or without return is fine. Why? This is so different from C++.

Thanks

Upvotes: 0

Views: 293

Answers (4)

Chinmay Kanchi
Chinmay Kanchi

Reputation: 66013

Consider the following C++ program:

#include <vector>
#include <iostream>

void add_val(std::vector<int> addTo, int addThis)
{
    for(std::vector<int>::iterator it = addTo.begin(); it!=addTo.end(); ++it)
    {
        *it += addThis;
    }
}

void add_ref(std::vector<int>& addTo, int addThis)
{
    for(std::vector<int>::iterator it = addTo.begin(); it!=addTo.end(); ++it)
    {
        *it += addThis;
    }
}

int main()
{
    std::vector<int> myVector;

    myVector.push_back(1);
    myVector.push_back(2);
    myVector.push_back(3);

    add_val(myVector, 3);

    std::cout<<"After add_val"<<std::endl;
    for (std::vector<int>::iterator it = myVector.begin(); it!=myVector.end(); ++it)
    {
        std::cout<<*it<<" ";
    }

    std::cout<<std::endl;

    add_ref(myVector, 3);

    std::cout<<"After add_ref"<<std::endl;
    for (std::vector<int>::iterator it = myVector.begin(); it!=myVector.end(); ++it)
    {
        std::cout<<*it<<" ";
    }
    std::cout<<std::endl;

    return 0;
}

The program outputs:

After add_val
1 2 3 
After add_ref
4 5 6 

Passing the vector to add_val() results in the original vector remaining unchanged, since it is passed by value. Passing the vector to add_ref() however, causes the values inside the original vector to change, since it's passed by reference.

In Python everything is passed by reference. However, a lot of the builtin types (str, tuple, int, float, etc.) are immutable. This means that any operation you perform on these types results in a new variable being bound in the current scope with the new value. For mutable types (list, dict, etc.), you end up with exactly the same result as passing a parameter by reference in C++.

Upvotes: 0

Alex Martelli
Alex Martelli

Reputation: 882541

But why did the person omits the return? Either with or without return is fine. Why? This is so different from C++.

Not at all - it's identical to C++ to all intent and purposes! Just make, in the C++ version, a void add and pass its argument a, say a std::vector<int>, by reference -- to all intents and purposes, this is what this Python add is doing, seen in C++ terms.

In Python terms, when a function "falls off the end" that's exactly the same as if it executed return None at that point. It's better style in such cases (when a function always ends by "falling off the end") to avoid the redundant return None statement (don't waste pixels and screen space in redundant ornamentation of this kind).

Upvotes: 7

ThiefMaster
ThiefMaster

Reputation: 318688

Everything is passed by reference in python, but integers, strings etc. are immutable so when you change it you create a new one which is bound to the local variable so the variable passed to the function isn't changed. Lists and dicts are, however, mutable - so if you change them no new object is created and due to this the change also affects the variable in the caller's scope.

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799240

add() mutates a instead of rebinding it, so the change shows up in the original object.

Upvotes: 1

Related Questions