Is the `.0` variable in` locals () `unavailable affecting memory or performance?

I support a project that has a function definition like this:

def f(a, (b1, b2), c):
    print locals()

When debugging the code, I found that locals()a key .1with a value appeared in (b1, b2). A quick check showed that the definition of the function is as follows:

def f((a1, a2)):
    print locals()

will have a .0key in locals()with a value (a1, a2). I was surprised by this behavior, but could not find any information in the Python documentation.

My questions are: do these unacceptable positional variables affect memory or performance? Are they documented anywhere? What purpose do they fulfill?

This project is a feedparser channel that is based on SAX and can potentially have tens or hundreds of function calls that would be affected by this behavior.

+5
source share
2 answers

so pep 3113 , as pointed out by Arthur Gaspard, contains the complete answer. It also lists a whole bunch of reasons why this is probably not a great example. One of them you found in the annoying side effects of debugging. The more I think, is that your code will break by switching to python3, but I'm not sure / still 2.7 personally.

I wanted to play with what is happening. As some disassembled bytecodes, we can see what happens with these three functions (spoiler: foo and bar have the same bytecodes):

from dis import dis

def foo(a, (b, c) ,d):
    return a + b + c + d

def bar(a, b_c, d):
    b, c = b_c
    return a + b + c + d

def baz(a, b, c, d):
    return a + b + c + d

print '\nfoo:'
dis(foo)
print '\nbar:'
dis(bar)
print '\nbaz:'
dis(baz)

Productivity:

foo:
  3           0 LOAD_FAST                1 (.1)
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               3 (b)
              9 STORE_FAST               4 (c)

  4          12 LOAD_FAST                0 (a)
             15 LOAD_FAST                3 (b)
             18 BINARY_ADD          
             19 LOAD_FAST                4 (c)
             22 BINARY_ADD          
             23 LOAD_FAST                2 (d)
             26 BINARY_ADD          
             27 RETURN_VALUE        


bar:
  7           0 LOAD_FAST                1 (b_c)
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               3 (b)
              9 STORE_FAST               4 (c)

  8          12 LOAD_FAST                0 (a)
             15 LOAD_FAST                3 (b)
             18 BINARY_ADD          
             19 LOAD_FAST                4 (c)
             22 BINARY_ADD          
             23 LOAD_FAST                2 (d)
             26 BINARY_ADD          
             27 RETURN_VALUE        


baz:
 11           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BINARY_ADD          
              7 LOAD_FAST                2 (c)
             10 BINARY_ADD          
             11 LOAD_FAST                3 (d)
             14 BINARY_ADD          
             15 RETURN_VALUE        

. foo bar , baz . , , , , , ( P)

+5

, .

>>> import timeit
>>> 
>>> 
>>> def function_1(a, (b1, b2), c):
...     locals()
... 
>>> def function_2(a, b1, b2, c):
...     locals()
... 
>>> 
>>> object_1 = object()
>>> object_2 = object()
>>> object_3 = object()
>>> tuple_of_objects_2_and_3 = (object_2, object_3)
>>> object_4 = object()
>>> 
>>> n = 100000000
>>> 
>>> time_1 = timeit.timeit(lambda: function_1(object_1, tuple_of_objects_2_and_3, 
...                                           object_4),
...                        number=n)
>>> time_2 = timeit.timeit(lambda: function_2(object_1, object_2, object_3, 
...                                           object_4), 
...                        number=n)
>>> 
>>> print(time_1, time_2)
(170.2440218925476, 151.92010402679443)

, .

+3

All Articles