Python how to take a list as a parameter and edit its values?

心已入冬 提交于 2019-12-13 13:44:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!