1
def divide(alist):
    # when the list have only one element, it should return the 0
    if len(alist) == 1:
        alist[:] = list([0])

    else:
        middle = len(alist) / 2
        divide(alist[:middle])
        divide(alist[middle:])
temp = [1, 2, 3, 4, 5, 6]
divide(temp)
print temp

In my function, after the recursion, i want to get the [0, 0, 0, 0, 0, 0],but temp is still the [1, 2, 3, 4, 5, 6]. And i also use alist[:] = list([0])to ensure the alist to be re-assigned.

Why? Is there something wrong with the reference?

2
  • What are you trying to achieve? Commented Jun 4, 2017 at 13:20
  • @Saif Asif I'm working on divide and conquer, so this is just the structure i set up. Commented Jun 5, 2017 at 7:40

2 Answers 2

2

Your code doesn't work becuase slicing as in divide(alist[:middle]) creates a new list, so alist after the first recursion doesn't refer to temp anymore.

It is more common to return results rather than trying to create side effects in the calling arguments, e.g.:

def divide(alist):
    # when the list have only one element, it should return the 0
    if len(alist) == 1:
        return [0]
    middle = len(alist) // 2
    return divide(alist[:middle]) + divide(alist[middle:])

print(divide(temp))
# [0, 0, 0, 0, 0, 0]

Obviously, this is relatively nonsense but I'm assuming you are just setting up the structure to do something specific.

If you really wanted to do this with side effects (not recommended!!!) then you would need to keep a left and right index and use that to eventually assign the [0], e.g.:

def divide(alist, left, right):
    middle = (right - left) // 2

    # when the list have only one element, it should return the 0
    if middle == 0:
        alist[left:right] = [0]
    else:
        divide(alist, left, left+middle)
        divide(alist, left+middle, right)

temp = [1, 2, 3, 4, 5, 6]
divide(temp, 0, len(temp))
print(temp)
# [0, 0, 0, 0, 0, 0]

If you want to keep the original calling signature then you can use an _inner() function to handle the recursion, which would allow you to default the args but in reality you could just return _inner(0, len(alist)) without them:

def divide(alist):
    def _inner(left=0, right=len(alist)):  # default args based on comment @EricDuminil
        middle = (right - left) // 2
        # when the list have only one element, it should return the 0
        if middle == 0:
            alist[left:right] = [0]
        else:
            _inner(left, left+middle)
            _inner(left+middle, right)
    return _inner()

temp = [1, 2, 3, 4, 5, 6]
divide(temp)
print(temp)
# [0, 0, 0, 0, 0, 0]
Sign up to request clarification or add additional context in comments.

3 Comments

It would be nice to be able to write def divide(alist, left=0, right=len(alist)). Sadly, it doesn't work in Python.
You can have an inner function that does the recursion to keep the outer call simpler (see edit) but I would still recommend against side-effect based recursion. It is generally considered bad practice and subtle errors are harder to fix.
It helps me a lot!Thanks!
1

Please mention your intented goal next time you ask a question. My guess was that you didn't need both recursion and in-place modification of your list.

So my first answer was to propose in-place modification without recursion :

def set_to_zero(alist):
    alist[:] = [0 for _ in alist]

temp = [1, 2, 3, 4, 5, 6]
set_to_zero(temp)
print(temp)
# [0, 0, 0, 0, 0, 0]

It turns out that you need recursion without in-place modification, because you want to write a merge sort.

Merge sort's most common implementation does not sort in place;[5] therefore, the memory size of the input must be allocated for the sorted output to be stored in (see below for versions that need only n/2 extra spaces).

Here's a clean implementation of the sort, with some debug lines. Here's a related question on SO (Mergesort python) with many implementations.

6 Comments

-1 the OP has simply come up with a redundant but similar problem to their actual problem and this answer would only help in this specific incidence, rather than someone being able to modify the other answer to fit their needs.
@cairdcoinheringaahing: Thanks for the feedback. I'm not sure I understand your point, though. How do you know that?
just a guess but my main point is that it can't really be replicated. Whenever I get code off SO it's usually the code that only needs a couple of edits to apply to my situation.
@cairdcoinheringaahing: Okay. Let's wait for some clarification from the OP. I don't understand what the purpose of this function really is.
I am going to implement the merge sort which needs the divide and conquer, so this is just the similar abstract structure :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.