Hello,
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?
Many thank!
Rachel
----------------------------
import xlwt as excel
import random
import copy
def getTitleList():
""" Makes a list of all the lines in a file """
filename = raw_input("Name and Extension of File: ")
myFile = open( filename )
titles = []
title = "none"
while title != "":
title = myFile.readline()
if title not in ["\n",""]:
titles.append(title)
return titles
def rank( titles ):
""" Gets a user-input ranking for each line of text.
Returns those rankings
"""
ranks = []
for t in titles:
rank = raw_input(t + " ")
ranks.append(rank)
return ranks
def rankRandom( titles ):
""" Takes a list of titles, puts them in random order, gets ranks, and then
returns the ranks to their original order (so that the rankings always
match the correct titles).
"""
finalRanks = [0]*len(titles)
origTitles = copy.copy(titles)
#print "Orign: ", origTitles
random.shuffle(titles) # Shuffle works in-place
ranks = rank(titles)
i = 0
for t in titles:
finalRanks[ origTitles.index(t) ] = ranks[i]
i += 1
titles = origTitles # Must restore, since python passes by reference, not
# value, and the original structure was changed by
# shuffle
#print "t: ", titles
return finalRanks
def writeToExcel(titles, allRanks):
# Open new workbook
mydoc = excel.Workbook()
# Add a worksheet
mysheet = mydoc.add_sheet("Ranks")
# Write headers
header_font = excel.Font() # Make a font object
header_font.bold = True
header_font.underline = True
# Header font needs to be style, actually
header_style = excel.XFStyle(); header_style.font = header_font
# Write Headers: write( row, col, data, style )
row = 0
col = 0
for t in titles:
# Write data. Indexing is zero based, row then column
mysheet.write(row, col, t, header_style)
col += 1
# Write Data
row += 1
for ranks in allRanks:
col = 0
for r in ranks:
mysheet.write(row, col, r)
col += 1
row += 1
# Save file. You don't have to close it like you do with a file object
mydoc.save("r.xls")
def main():
listOfTitles = getTitleList()
allRanks = []
done = raw_input("Done?: ")
while done != "y":
allRanks.append( rankRandom( listOfTitles ) )
#print listOfTitles
done = raw_input("Done?: ")
writeToExcel(listOfTitles, allRanks )
if __name__ == "__main__" : main()
_______________________________________________
Tutor maillist - [email protected]
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor