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

Reply via email to