Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does python VM have co_names instead of just using co_consts?

A code object generated by Python compiler contains a tuple of constants used in the instructions (named co_consts) and also a tuple containing names (named co_names).

Why having two distinct lists? Wouldn't be simpler to just use co_consts for names too?

like image 234
6502 Avatar asked Jan 28 '15 08:01

6502


2 Answers

Consider the following function.

def f(x):
    x += n
    return x * 4

Here x is a local name, its value can change. 4 is a constant. Its value will never change. However, it's still an object and it's better to cache them rather than create a new object each time it's needed. Finally, n is a global reference. The string "n" is stored by the function so that it can be used as a key to retrieve n from the function's global context.

>>> f.__code__.co_nlocals # just 1 (for x)
1
>>> f.__code__.co_consts
(None, 4)
>>> f.__code__.co_names
('n',)
>>> "n" in f.__globals__ and globals() is f.__globals__
True

The reason for keeping names and consts separate is for the purposes of introspection. The only real reason to merge the tuples would be memory efficiency, though this would only gain you one object and one pointer per function. Consider the following function.

def g():
    return "s" * n

If the tuple containing consts was merged with the tuple containing names then you (not the VM) wouldn't be able to tell which values were for accessing globals and which were constants of the function.

like image 89
Dunes Avatar answered Nov 09 '22 07:11

Dunes


I know this answer is like 11 months out of date but from my tinkering it seems the following is happening

To access co_names in bytecode, one uses LOAD_GLOBAL(co names index) and this pushes a reference to the desired co_names onto the stack, eg its indirect

To access co_consts in bytecode, one uses LOAD_CONST(co consts index) and this pushes the actual value stored at the desired co_consts onto the stack, eg its direct

I'm not sure it has any direct bearing at a python level, but at a bytecode level its a profound difference

like image 1
Bitmap Image Avatar answered Nov 09 '22 07:11

Bitmap Image