Compile time evaluation of dictionaries
Terry Reedy
tjreedy at udel.edu
Thu Mar 10 17:40:40 EST 2011
On 3/10/2011 11:23 AM, Gerald Britton wrote:
> Today I noticed that an expression like this:
>
> "one:%(one)s two:%(two)s" % {"one": "is the loneliest number", "two":
> "can be as bad as one"}
>
> could be evaluated at compile time, but is not:
In fact, it could be evaluated at writing time ;-).
This would be an example of constant folding, except that a dict is not,
in itself, a constant.
>>>> dis(compile(
> ... '"one:%(one)s two:%(two)s" % {"one": "is the loneliest number",
> "two": "can be as bad as one"}',
> ... '','exec'))
> 1 0 LOAD_CONST 0 ('one:%(one)s two:%(two)s')
> 3 BUILD_MAP 2
> 6 LOAD_CONST 1 ('is the loneliest number')
> 9 LOAD_CONST 2 ('one')
> 12 STORE_MAP
> 13 LOAD_CONST 3 ('can be as bad as one')
> 16 LOAD_CONST 4 ('two')
> 19 STORE_MAP
> 20 BINARY_MODULO
> 21 POP_TOP
> 22 LOAD_CONST 5 (None)
> 25 RETURN_VALUE
>>>>
>
> Any idea why Python works this way?
Because that is how the language is defined.
> I see that, in 3.2, an
> optimization was done for sets (See "Optimizations" at
> http://docs.python.org/py3k/whatsnew/3.2.html) though I do not see
> anything similar for dictionaries.
I presume you mean this:
"Python’s peephole optimizer now recognizes patterns such x in {1, 2, 3}
as being a test for membership in a set of constants. The optimizer
recasts the set as a frozenset and stores the pre-built constant.
Now that the speed penalty is gone, it is practical to start writing
membership tests using set-notation. This style is both semantically
clear and operationally fast:
extension = name.rpartition('.')[2]
if extension in {'xml', 'html', 'xhtml', 'css'}:
handle(name)
(Patch and additional tests contributed by Dave Malcolm; issue 6690)."
This is possible because: sets have a frozen counterpart, and cpython
*sometimes* follows an 'as if' rule for optimizations. There is no
frozendict, so the same pattern could not be followed.
Note first that the optimization is *not* an example of constant
folding, but recognition that an unbound mutable cannot be mutated, and
therefore, if all its contents are fixed, can be 'cast' to constant form
at compile time.
Note second that the optimization does not apply to all such set
instances, but only to this particular 'in' context. It follows a
similar optimization for turning lists into tuples (although in this
latter case, the programmer could have remembered to use () instead of []).
The optimization *did* happen because various people started an issue,
wrote a patch, reviewed the patch, and committed it to the cpython
source. You might read the issue if you have not:
http://bugs.python.org/issue6690
Terry Jan Reedy
More information about the Python-list
mailing list