On Wed, May 25, 2011 at 6:14 AM, Rachel-Mikel ArceJaeger <arcejae...@gmail.com> wrote:
> I am having trouble with determining when python is passing by reference and > by value and how to fix it to do what I want: > > I am writing a program that will take in a list of book titles and will allow > many people to rank them in terms of popularity and will export the results > to Excel. I'll include the whole code below, but the function I'm having > trouble with is rankRandom(). I want it to take in a list of titles, > randomize the list (so that I can be certain the order isn't influencing the > results of the rankings), get a person's rankings, and then resort the order > of the rankings to match the original order of title list (that way I can > match up different people's rankings to the correct title). > > The issue is this: random.shuffle() mutates the list in place, rather than > creating a new copy. This is fine, but rather than modifying just the local > copy of my titles, it is modifying it in the other functions, too. For > instance, rankRandom() is called by main(), which passes it listOfTitles. > When rankRandom() returns, listOfTitles has been changed to the randomized > version of titles. > > To fix this, I tried copying the original title list and then assigning it to > the mutated version right before the rankRandom() function returns. The local > version of titles in rankRandom() does indeed regain its original value, but > listOfTitles in main() is still being assigned to the randomized version, and > not to the original version. This boggles me, since it seems like shuffle is > mutating the titles as if it were a global variable, but assignment is > treating it only as a local. > > What exactly is going on here, and how do I avoid this problem? You should not think of 'pass by reference' or 'pass by value'. That's how things work in the C world. In Python, the data model is that variables are a name for an object. What you are providing when calling an argument with a function is not the variable itself, be it by reference or by value, but the object that the variable refers to. Thus, in your code, when calling rank_random(), "title" becomes (within the function) a name of the object that also has the name listOfTitles in main(). This object is then changed by random.shuffle(). The assignment titles = origTitles gives the object referred to by origTitles a new name, 'titles'. This does _not_ change the object that originally had the name titles, which thus still has the shuffled value. As for how to do what you wanted to do, do make a copy like you do, but then _do the shuffling on the copy_. You could also change the call to the function to have a copy rather than the original variable as its argument, but that solution is not as useful for re-use of the function. Oh, and one more remark: copying a list objects is often done using objects[:] rather than copy.copy(objects) -- André Engels, andreeng...@gmail.com _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor