[Python-ideas] Allow function __globals__ to be arbitrary mapping not just dict

Eric Snow ericsnowcurrently at gmail.com
Sun Mar 18 22:58:05 CET 2012


On Sun, Mar 18, 2012 at 5:27 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Currently, if you try to construct a function from parts, the mapping that
> becomes func.__globals__ must be an actual dict:
>
>
> py> class Mapping:
> ...     def __getitem__(self, key):
> ...             if key == 'y':
> ...                     return 42
> ...             raise KeyError(key)
> ...
> py> from types import FunctionType
> py> f = lambda x: x + y
> py> g = FunctionType(f.__code__, Mapping(), 'g')
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: function() argument 2 must be dict, not Mapping
>
>
> I propose to allow function.__globals__ to accept any mapping type.
>
> That, plus the new collections.ChainMap class in Python 3.3, would allow
> some interesting experiments with namespaces and scoping rules.
>
> E.g. if I want to write a function with a custom namespace, I have to do
> something like this:
>
>
> ns = ChainMap( ... )  # set up a namespace
> def func(a, ns=ns):
>    x = a + ns['b']
>    y = ns['some_func'](ns['c'])
>    z = ns['another_func'](x, y)
>    ns['d'] = (x, y, z)
>    return ns['one_last_thing'](d)
>
>
> which is not a very natural way of writing code. But if we could use
> non-dict mappings as __globals__, I could write that function like this:
>
>
> ns = ChainMap( ... )  # set up a namespace
> def func(a):
>    global d
>    x = a + b
>    y = some_func(c)
>    z = another_func(x, y)
>    d = (x, y, z)
>    return one_last_thing(d)
>
>
> # This could be a decorator.
> func = FunctionType(func.__code__, ns, func.__name__)
>
>
>
> (By the way, ChainMap is only one possible example namespace.)

A casual search of the archives identifies some similar discussion
over the years [1].

If PyEval_EvalCodeEx were more fully exposed in Python things would be
simpler (see function_call() [2]).  I made a small effort to that
effect last year, but it turned out to be relatively unnecessary.
However, I didn't factor in the restriction on the type of globals...

-eric

[1] past discussion/efforts:
     http://www.python.org/download/releases/2.2/descrintro/#subclassing
(optimization surrounding globals as dict)
     http://mail.python.org/pipermail/python-dev/2002-October/029752.html
     http://mail.python.org/pipermail/python-dev/2002-October/029753.html
     http://mail.python.org/pipermail/python-dev/2002-October/029761.html
     http://bugs.python.org/issue215126
     http://mail.python.org/pipermail/python-list/2010-December/1262045.html
[2] http://hg.python.org/cpython/file/default/Objects/funcobject.c#l592



More information about the Python-ideas mailing list