Why does 1 + 1 not use BINARY_ADD?

I'm doing it:

>>> dis.dis(lambda: 1 + 1)
0 LOAD_CONST        2 (2)
3 RETURN_VALUE

I expected the operation code BINARY_ADD to do the addition. How was the amount calculated?

+4
source share
2 answers

This is the work of the Python peephole optimizer. It evaluates simple operations only with constants during compilation itself and saves the result as a constant in the generated bytecode.

Quote from Python 2.7.9 Source Code ,

            /* Fold binary ops on constants.
               LOAD_CONST c1 LOAD_CONST c2 BINOP -->  LOAD_CONST binop(c1,c2) */
        case BINARY_POWER:
        case BINARY_MULTIPLY:
        case BINARY_TRUE_DIVIDE:
        case BINARY_FLOOR_DIVIDE:
        case BINARY_MODULO:
        case BINARY_ADD:
        case BINARY_SUBTRACT:
        case BINARY_SUBSCR:
        case BINARY_LSHIFT:
        case BINARY_RSHIFT:
        case BINARY_AND:
        case BINARY_XOR:
        case BINARY_OR:
            if (lastlc >= 2 &&
                ISBASICBLOCK(blocks, i-6, 7) &&
                fold_binops_on_constants(&codestr[i-6], consts)) {
                i -= 2;
                assert(codestr[i] == LOAD_CONST);
                cumlc = 1;
            }
            break;

Basically, he is looking for instructions like this

LOAD_CONST c1
LOAD_CONST c2
BINARY_OPERATION

and evaluates it and replaces these instructions with result and command LOAD_CONST. Quoting a comment in a functionfold_binops_on_constants ,

/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
   with    LOAD_CONST binop(c1,c2)
   The consts table must still be in list form so that the
   new constant can be appended.
   Called with codestr pointing to the first LOAD_CONST.
   Abandons the transformation if the folding fails (i.e.  1+'a').
   If the new constant is a sequence, only folds when the size
   is below a threshold value.  That keeps pyc files from
   becoming large in the presence of code like:  (None,)*1000.
*/

,

    case BINARY_ADD:
        newconst = PyNumber_Add(v, w);
        break;
+8

Python , 1 + 1, 2, , 2 ( !). , dis . -, 2.

, 1+1 -, dis.dis() , , 1+1 2.

- :

>>> dis.dis(lambda: x + 1)
  1           0 LOAD_GLOBAL              0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD          
              7 RETURN_VALUE  

, BINARY_ADD, x + 1 .

+1

Source: https://habr.com/ru/post/1570408/


All Articles