On Tue, Jul 30, 2019 at 12:13 PM Steven D'Aprano <st...@pearwood.info> wrote:
>
> On Mon, Jul 29, 2019 at 09:53:38PM -0400, Ricky Teachey wrote:
>
> > But I ask: how is it possible, then, to create a with block that "gobbles
> > up" things declared in it and adds those things to some namespace using
> > existing python syntax...?
> [...]
> > I currently can't create an object that allows this to work:
> >
> > with NameSpace('ns') as ns:
> >     a = 1
> > assert ns.a=1
>
> Neither can I, and I've been mucking about with this idea for about
> three years. (To be honest, I poke it with a stick about every six
> months, so its not like I've spend a lot of time on it.)
>
> I kinda-sorta got it to work with a class statement plus a decorator,
> not too different from your metaclass example, but couldn't get
> functions to work correctly.

A class + decorator gets so almost there that it might be possible
with just a tiny bit of language support. What if there could be a way
to change a function's __globals__? Currently that's readonly
according to funcobject.c, but by hacking that flag out, I can create
the following example:

def namespace(cls):
    """Decorate a class to turn it into a namespace"""
    ns = dict(cls.__dict__)
    for member in ns.values():
        if hasattr(member, "__globals__"):
            member.__globals__ = ns
    return cls

@namespace
class ns:
    x = 1
    def foo(y):
        return x + y
    def replace(new_x):
        global x
        x = new_x

print(ns.foo(4)) # 5
ns.replace(100)
print(ns.foo(4)) # 104


Due to CPython limitations, the new __globals__ MUST be a plain dict
(not the mappingproxy that cls.__dict__ is, and not a ChainMap), but
this is extremely close to what could actually be quite useful. Also,
since the function objects get mutated by the decorator, calling a
function during the namespace's construction will have the wrong
behaviour. Maybe the only language support needed is some way to say
"from now on, functions should be created with THIS value for their
globals"?

It might be possible to get even closer using a metaclass rather than
a decorator.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FAE7WDCKTH272M6LTUJ3QEUIOEMKJIVD/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to