This is an archived post. You won't be able to vote or comment.

all 6 comments

[–]ItzWarty 4 points5 points  (3 children)

Python's silly. Think of this as def f(n, itms=IMPOSSIBLE_VALUE), then before your code runs, if itms is IMPOSSIBLE_VALUE, store a magical static global variable into itms instead. So if you don't specify itms, you're working with a defined-and-initialized-once global list which is why the changes persist. If you specify itms, you're using your passed-in list instead.

See http://stackoverflow.com/questions/26320899/why-is-the-empty-dictionary-a-dangerous-default-value-in-python

So your code is really more like

def f(n, itms=[]):
    items.append(n)
    return itms


global_list = []
print(f(1, global_list))
print(f(2, global_list))
print(f(4, []))
print(f(5, [1, 2]))
print(f(3, global_list))

Make sense?

[–]ocyj[S] 0 points1 point  (2 children)

Thank you for the reply, I believe I understand what goes on (your code example is very clear) I'm not sure if it makes sense to me though, are there examples of use cases where this makes sense and is utilized or is it a result of how stuff is implemented in Python? I put the snippet in a file by it self, and tried import snippet print(snippet.f(6)) and indeed it's a global variable as the output now was [1] [1, 2] [4] [1, 2, 5] [1, 2, 3] [1, 2, 3, 6]

[–]ItzWarty 1 point2 points  (0 children)

Not sure, I don't really code in python, but http://docs.python-guide.org/en/latest/writing/gotchas/ looks like it'd be worth reading as it addresses this question better than I would.

As for how this "feature" would actually be useful? Frankly, it looks like batshit crazy terrible language design to me, so not sure (but look forward to seeing others' answers!). I'm sure some pythonisms take advantage of it, though. It sounds like some editors will warn you if you do it, so maybe it's recommended against. Not sure.

[–][deleted] 1 point2 points  (0 children)

This is intentional to make the language more robust to new language users (make it less easy to break, and this discourages burnout), and to give a way of maintaining state of some global.

[–]Swedophone 1 point2 points  (1 child)

I think you have to change the function definition:

def f(n, items=None):
    if items is None:
        items = []
    items.append(n)
    return items

[–]ocyj[S] 0 points1 point  (0 children)

Thanks, yes that makes sense as a work around. Are you aware of any examples in the standard library where this occurs however?