multiple namespaces within a single module?

Arnaud Delobelle arnodel at gmail.com
Fri Feb 10 11:41:06 CET 2012


On 10 February 2012 00:05, Ethan Furman <ethan at stoneleaf.us> wrote:
> Ethan Furman wrote:
>>
>> Hrm -- and functions/classes/etc would have to refer to each other that
>> way as well inside the namespace... not sure I'm in love with that...
>
>
>
> Not sure I hate it, either.  ;)
>
> Slightly more sophisticated code:
>
> <code>
> class NameSpace(object):
>    def __init__(self, current_globals):
>        self.globals = current_globals
>        self.saved_globals = current_globals.copy()
>
>    def __enter__(self):
>        return self
>    def __exit__(self, *args):
>        new_items = []
>        for key, value in self.globals.items():
>            if (key not in self.saved_globals and value is not self
>                    or key in self.saved_globals
>                    and value != self.saved_globals[key]):
>
>                new_items.append((key, value))
>        for key, value in new_items:
>            setattr(self, key, value)
>            del self.globals[key]
>        self.globals.update(self.saved_globals)
>
> if __name__ == '__main__':
>    x = 'inside main!'
>    with NameSpace(globals()) as a:
>        x = 'inside a?'
>        def fn1():
>            print(a.x)
>    with NameSpace(globals()) as b:
>        x = 'inside b?'
>        def fn1():
>            print(b.x)
>        def fn2():
>            print('hello!')
>            b.fn1()
>    y = 'still inside main'
>    a.fn1()
>    b.fn1()
>    print(x)
>    print(y)
> </code>

Please! Metaclasses are the obvious way to proceed here :)  Then there
is no need for the 'a.x' and 'b.x' cruft.

marigold:junk arno$ cat namespace.py
function = type(lambda:0)

def change_globals(f, g):
    return function(f.__code__, g, f.__name__, f.__defaults__, f.__closure__)

class MetaNamespace(type):
    def __new__(self, name, bases, attrs):
        attrs['__builtins__'] = __builtins__
        for name, value in attrs.items():
            if isinstance(value, function):
                attrs[name] = change_globals(value, attrs)
        return type.__new__(self, name, bases, attrs)

class Namespace(metaclass=MetaNamespace):
    pass


x = "inside main"

class a(Namespace):
    x = "inside a"
    def fn1():
        print(x)

class b(Namespace):
    x = "inside b"
    def fn1():
        print(x)
    def fn2():
        print("hello")
        fn1()

y = "inside main"

a.fn1()
b.fn1()
b.fn2()
print(x)
print(y)
marigold:junk arno$ python3 namespace.py
inside a
inside b
hello
inside b
inside main
inside main

A bit more work would be needed to support nested functions and closures...

-- 
Arnaud



More information about the Python-list mailing list