Two curious errors when function globals are manipulated

eryk sun eryksun at gmail.com
Tue Jul 5 12:13:59 EDT 2016


On Tue, Jul 5, 2016 at 3:50 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> It works with exec:
>
> py> from collections import ChainMap
> py> class ChainDict(ChainMap, dict):
> ...     pass
> ...
> py> m = ChainDict()
> py> exec("x = 1", m, m)
> py> m['x']
> 1
>
> (Tested in both 3.3 and 3.6.)

No, actually it doesn't work. Remember that when you store to a
variable, it's implicitly a local variable, for which CPython uses
STORE_NAME in unoptimized code. To test this properly you need to
declare the variable as global, so that it uses STORE_GLOBAL:

    import dis
    from collections import ChainMap

    class ChainDict(ChainMap, dict):
        pass

    m = ChainDict()
    code = compile(r'''
    global x
    x, y = 1, 2
    ''', '', 'exec')

    >>> dis.dis(code)
      3           0 LOAD_CONST               3 ((1, 2))
                  2 UNPACK_SEQUENCE          2
                  4 STORE_GLOBAL             0 (x)
                  6 STORE_NAME               1 (y)
                  8 LOAD_CONST               2 (None)
                 10 RETURN_VALUE

    >>> exec(code, m)
    >>> m
    ChainDict({'y': 2})



More information about the Python-list mailing list