问题
I have the following code:
def radixSort(A):
#get max amount of digits
A = sortByDigit(A, maxDigits) #this works
print(A) #prints A as sorted
if __name__ == "__main__":
A = [int(100*random.random()) for i in range(10)]
radixSort(A)
print(A) #prints unsorted
Why does changing A in radixSort not change A in the main method ? I realize I could simply add a return statement in radixSort, and an assignment statement in the main method, but the code has to pass the following test case:
def testrRadixSort(self):
A = [4, 3, 2]
radixSort(A)
self.assertEqual(A, [4,3,2])
回答1:
sortByDigit isn't sorting inplace. It's creating a new list and returning a reference to that.
You can replace the contents of A with the content of the new list with this simple change
A[:] = sortByDigit(A, maxDigits) #this works
Alternatively you could modify sortByDigit so it does sort inplace
回答2:
The problem is on this line:
A = sortByDigit(A, maxDigits)
You created a local assignment of A, which does not overwrite the global copy of A.
You need to make sortByDigit modify the contents of A, not return a new list.
An alternative is to add
global A
Before that line so it will modify the global A.
However with regards to global variables see kindall's comment below.
回答3:
This behaviour is about passing arguments by reference or by value. There already is a great explanation of this behaviour on StackOverflow.
This means: You cannot reassign the given list, but you can modify the existing instance, e. g. with the append method.
回答4:
I'm assuming sortByDigit() returns a sorted copy of the list rather than sorting it in place. In which case, simply replace the contents of the list with the result of that call, via slice assignment:
A[:] = sortByDigit(A, maxDigits)
回答5:
Nah, you can't change A like that. Keep in mind that A in your radixSort function (local scope) is different with A in your main function (global scope).
To achieve what you need, you can declare it as a global variable. However, this is not the best method since using global vars can get you to a confusing scope problem, therefore it's not recommended. But this how to do it:
def radixSort(lst): #we can refer to the passed variable as lst
global A
This doesn't sort A inplace, but it assigns the sorted lst to A.
Or better, assign the sorted value to A with slice notation:
A[:] = sortByDigit(A, maxDigits) #store the sorted list in A
Or even better, return it as sorted, and then reassign A with the sorted value:
def radixSort(A):
#get max amount of digits
A = sortByDigit(A, maxDigits) #this works
print(A) #prints A as sorted
return A
And in your main program:
if __name__ == "__main__":
A = [int(100*random.random()) for i in range(10)]
A = radixSort(A)
print(A) #prints sorted
self.assertEqual(A, [4,3,2]) #self.assertEqual(sorted, unsorted)
Also, it's not a good practice to capitalize identifiers. Capitalized words is usually reserved for classes.
So:
def radixSort(a):
#get max amount of digits
a = sortByDigit(a, maxDigits) #this works
print(a) #prints A as sorted
return a
if __name__ == "__main__":
a = [int(100*random.random()) for i in range(10)]
a = radixSort(a)
print(a) #prints sorted
self.assertEqual(A, [4,3,2]) #self.assertEqual(sorted, unsorted)
Hope this helps!
来源:https://stackoverflow.com/questions/19625946/python-how-to-take-a-list-as-a-parameter-and-edit-its-values