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 - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor