0

I am having a problem which is hard to explain because there's a lot of code involve. So it boils down to the following problem.

I am trying to access the list xxx outside the function foo but I am getting unexpected results. Can someone please explain why?

Here's my function which I have created to show the problem:

def foo(xxx = []):
    if len(xxx) == 5:
        return xxx
    xxx += [1]
    foo()
    return xxx

If I run

print foo()

I get

[1, 1, 1, 1, 1]

which is what I expect.

But I want the list xxx to be accessible outside foo. So, I am doing

xxx = []
print foo(xxx)
print xxx

Now I expect to get the list xxx to be

[1, 1, 1, 1, 1]

but what I am getting xxx to be, is

[1]

which is not what I expect.

Can someone explain why? And is it possible to access the correct xxx outside foo without accessing it through the output of the function foo? The reason I want to do this is because in my actual code I am returning something other than in my function foo and making changes to xxx which I want to see after the foo has executed. I can make the function also return xxx every time but this will make my code unnecessarily bulky. But I am not sure if I am compromising the code quality. I don't know. Please suggest which ever way is the best.

Thanks

5
  • Passing in an argument replaces the default argument. So it will happily modify a different list when provided (and that list will be modified even if not returned), otherwise it's modifying the shared list used as a default (which cannot be accessed normally without returning it). Commented Oct 8, 2015 at 11:29
  • Just a side note (that has nothing to do with your question): try to avoid mutable default arguments. Their behavior is counter intuitive and people using your code may get unexpected results. Commented Oct 8, 2015 at 11:31
  • I am myself very confused with this code. What's the substitute for mutable default arguments? Commented Oct 8, 2015 at 11:33
  • It depends: what are you trying to do? Commented Oct 8, 2015 at 11:36
  • I found my answer. By using the code by @Hammerite I am getting the desired functionality. Thanks Commented Oct 8, 2015 at 11:39

1 Answer 1

3
xxx = []
print foo(xxx)
print xxx

In this code you are calling foo() with the list you created outside the function, called xxx. But within the function, you are recursing to call foo() without parameters, so it modifies the list that was created at function definition time by the expression for the default argument value. (Importantly, this is the same list every time you call the function without supplying a value for that argument.)

Compare what happens when you define foo like this instead:

def foo(xxx = None):
    if xxx is None:
        xxx = []
    if len(xxx) == 5:
        return xxx
    xxx += [1]
    foo()
    return xxx

... and what happens when you define it like this:

def foo(xxx = None):
    if xxx is None:
        xxx = []
    if len(xxx) == 5:
        return xxx
    xxx += [1]
    foo(xxx)
    return xxx
Sign up to request clarification or add additional context in comments.

2 Comments

The second code which you mentioned solved my problem. But trying understand the difference between all the three is spinning my mind.
Roughly speaking when you write foo(xxx=[]) the xxx value is initialized on the module level and would be shared between all calls to the function - not created every time you make a call. There is a lot of information about this on web and StackOverflow.

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.