2

First I wrote the first sample of code and it didn't work correctly. I prefer the first sample, but only the second one works correctly. I don't know why the first sample doesn't change the original array but second does. Where is the difference?

First sample:

import heapq

def heap_sort(tab):
    heap = []
    for i in tab:
        heapq.heappush(heap, i)
    tab = [heapq.heappop(heap) for _ in xrange(len(heap))]

temp_tab = [4, 3, 5, 1]
heap_sort(temp_tab)
print temp_tab

Prints:

[4, 3, 5, 1]

Second sample:

import heapq

def heap_sort(tab):
    heap = []
    for i in tab:
        heapq.heappush(heap, i)
    for i, _ in enumerate(tab):
        tab[i] = heapq.heappop(heap)

temp_tab = [4, 3, 5, 1]
heap_sort(temp_tab)
print temp_tab

Prints:

[1, 3, 4, 5]
  • 2
    In the first example, if you had assigned to `tab[:]` instead of `tab`, it would have worked. – Navith Apr 26 '15 at 22:26
  • 1
    What's the point of this code? Why don't you return heap instead of pushing everything back into tab? In fact, why not just sort the list and forget about the heap stuff altogether? – Daniel Roseman Apr 26 '15 at 22:31

3 Answers3

3

You could also use [:], that will change the original object passed in:

def heap_sort(tab):
    heap = []
    for i in tab:
        heapq.heappush(heap, i)
    tab[:] = [heapq.heappop(heap) for _ in xrange(len(heap))]

So instead of reassigning the name tab to a new object you are actually updating the original tab object.

You could also use a generator expression instead of building the whole list:

tab[:] = (heapq.heappop(heap) for _ in xrange(len(heap)))
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
2

Because you're just reassigning a new name called tab inside the function, it doesn't affect the global name tab you've defined. So, change your function to actually return the value, will work:

import heapq

def heap_sort(tab):
    heap = []
    for i in tab:
        heapq.heappush(heap, i)
    # return the supposed tab value
    return [heapq.heappop(heap) for _ in xrange(len(heap))]

tab = [4, 3, 5, 1]
# assign the tab to the returned value
tab = heap_sort(tab)
print tab
[1, 3, 4, 5]

For your reference, read How do I pass a variable by reference? will help you understand how the referencing works in Python.

Community
  • 1
  • 1
Anzel
  • 19,825
  • 5
  • 51
  • 52
  • But If I have different name (tab1 whatever) the results is the same. –  Apr 26 '15 at 22:28
  • 2
    @WuJo, The key is that, inside the function, they have no access to the global `tab`, it's just creating a new name called `tab`, once the function returns, that new `tab` value is disposed. – Anzel Apr 26 '15 at 22:29
  • @WuJo, so instead you reassign your global `tab` to the returned value from the function, will work. – Anzel Apr 26 '15 at 22:30
-1

Try this:

>>> def heap_sort(tab):
    heap=[]
    for i in tab:
        heapq.heappush(heap,i)
    heapq.heapify(heap)
    return heap

>>> t=heap_sort(t)
>>> print(t)
[1, 3, 5, 4]