I maintain a project that has a function definition similar to this:
def f(a, (b1, b2), c):
print locals()
While debugging the code I discovered that a .1 key appeared in locals(), with the value (b1, b2). A quick check revealed that a function definition like the following:
def f((a1, a2)):
print locals()
will have a .0 key in locals() with the value (a1, a2). I was surprised by this behavior, but could find no information in the Python documentation.
My questions are: do these otherwise-inaccessible positional variables affect memory or performance? Are they documented anywhere? What purpose do they serve?
The project in question is feedparser, which is SAX-based and could potentially have dozens or hundreds of function calls that would be affected by this behavior.
so pep 3113, as artur gaspar points out, contains a full answer. It also lists a whole bunch of reasons why this probably isn’t a great pattern to follow. One of these you discovered in the annoying side effects of debugging. A bigger one is I think that your code will break transitioning to python3, but I’m not sure/still am on 2.7 personally.
I wanted to play with what happens. Looking as some disassembled bytecodes we can see what happens with these three functions (spoiler: foo and bar have identical bytecodes):
Yields:
As you can see.
fooandbarare identical, whilebazskips the unpacking. So yes, this will affect performance a bit, but only as long as tuple unpacking takes, which should be negligible in everything except very small functions and toy examples (like this one ;P)