Say I have several variables or objects in Python, a
, b
, c
, ...
How can I easly dump these variables into a namespace in Python and restore them at a later time? (e.g. in the same way argparse
wraps various variables into a namespace).
Here are two examples of how I would like to dump things to and from a namespace:
function (bar):
# We start with a, b and c
a = 10
b = 20
c = "hello world"
# We can dump anything we want into e, by just passing things as arguments:
e = dump_into_namespace(a, b, c)
del a, b, c
print (e.a + e.b) # Prints 30
return e # We can return e if we want. This is just a use case scenario
# We start with e, which for example was built with a call to
# dump_into_namespace(a,b,c) somewhere else in the program,
# in which case e would hold a, b and c
# We may receive e through a function call or load it from disk, e.g.:
function foo(e):
# The following call creates the variables a,b and c
# or updates their values if the already exist in memory
dump_from_namespace(e)
del e
print(a + b) # Prints 30
print(c) # Prints hello world
My first question is: Is this possible at all in Python? (note that the method dump_into_namespace
does not directly receive the names of the variables, at least as far as I can tell).
If the answer to the above is no, how could I do it with an interface like this?
e = dump_into_namespace('a', 'b', 'c')
Also, how would this be done this with a dictionary instead of a namespace?
There are a few threads that seem relevant addressing a dot-access of dynamically-defined variables, but I don't think they address the problem of dumping variables:
Are there any libraries that facilitate this type of access through dot notation?
It looks like there is a library that supports dot-accessible dictionaries in Python, called Bunch, but I am not sure it would support easily dumping as I defined it.
Text Files The most basic way to save dictionaries in Python would be to store them as strings in text files.
Python Dictionary clear() Method The clear() method removes all the elements from a dictionary.
Namespaces are collections of different objects that are associated with unique names whose lifespan depends on the scope of a variable. The scope is a region from where we can access a particular object. There are three levels of scopes: built-in (outermost), global, and local.
The solution below provides syntax very close to your requirement, the only difference is that you have to pass to the function environment where the variables are defined explicitly:
x = 10
y = 20
class dump_into_namespace:
def __init__(self, env, *vars):
self.vars = dict([(x, env[x]) for v in vars for x in env if v is env[x]])
def __getattr__(self, name): return self.vars[name]
o = dump_into_namespace(locals(), x, y)
print o.x, o.y
You can then 'dump' back the variables to your locals (say, in a different function):
>>> locals().update(o.vars)
>>> x
10
Thanks to the suggestion of eyquem this can be even shorter. The idea is to put variables into self.__dict__
of the 'dump' object (note: syntax of update changes here):
class dump_into_namespace:
def __init__(self, env, *vs):
vars(self).update(dict([(x, env[x]) for v in vs for x in env if v is env[x]]))
def f():
x = 10
y = 20
return dump_into_namespace(locals(), x, y)
o = f()
print o.x, o.y
globals().update(vars(o))
print x
You have several options to create your 'namespace'. The easiest two are:
Create a quick custom class:
class Namespace(object):
def __init__(self, **kw):
self.__dict__.update(kw)
def dump_into_namespace(**kw):
return Namespace(**kw)
Call with dump_into_namespace(a='a', b='b', c='c')
; this takes an arbitrary number of keyword arguments.
Use a collections.namedtuple
class:
from collections import namedtuple
Namespace = namedtuple('Namespace', 'a b c')
def dump_into_namespace(a, b, c):
return Namespace(a, b, c)
Call with dump_into_namespace('a', 'b', 'c')
; this only takes a fixed number of arguments, but your dump_into_namespace()
function could provide defaults.
What you call 'dot notation' is really just attribute access.
To be honest, the easiest way is just to assign them:
e.a = a
e.b = b
e.c = c
You can't really do it more dynamically, because a variable doesn't know its own name. You would have to pass them as keyword arguments, in which case you can just update the namespace's __dict__
directly:
def dump_into_namespace(e, **kwargs):
e.__dict__.update(kwargs)
and you would have to call it as:
dump_into_namespace(e, a=a, b=b, c=c)
EDIT:
piokuc's answer inspired me to take account of the environnement
My solution updates self._dict_ so that there is no need to define a special function __getattr__
: the objects passed to the function become real attributes, their names belongs to the created object's dictionary.
def dump_into_ns(env,*x):
class A:
def __init__(self,*y):
vars(self).update((n,o) for n,o in env.items()
if o in y)
return A(*x)
a = 19
b = 'Monday'
c = 'Wednesday'
def ftry(x,y):
palat = 'obastey'
a = x -1
b = y +100
c = x*y -8
return dump_into_ns(locals(),a,b,c)
h = dump_into_ns(globals(),a,b,c)
print "h.__dict__ ==",h.__dict__
print '"a" in h.__dict__ ==',"a" in h.__dict__," h.a ==",h.a
print '"b" in h.__dict__ ==',"b" in h.__dict__," h.b ==",h.b
print '"c" in h.__dict__ ==',"c" in h.__dict__," h.c ==",h.c
print
e = ftry(20,50)
print "e.__dict__ ==",e.__dict__
print '"a" in e.__dict__ ==',"a" in e.__dict__," e.a ==",e.a
print '"b" in e.__dict__ ==',"b" in e.__dict__," e.b ==",e.b
print '"c" in e.__dict__ ==',"c" in e.__dict__," e.c ==",e.c
print
print 'h.a == e.a : ',h.a==e.a
print 'h.b == e.b : ',h.b==e.b
print 'h.c == e.c : ',h.c==e.c
result
h.__dict__ == {'a': 19, 'c': 'Wednesday', 'b': 'Monday'}
"a" in h.__dict__ == True h.a == 19
"b" in h.__dict__ == True h.b == Monday
"c" in h.__dict__ == True h.c == Wednesday
e.__dict__ == {'a': 19, 'c': 992, 'b': 150}
"a" in e.__dict__ == True e.a == 19
"b" in e.__dict__ == True e.b == 150
"c" in e.__dict__ == True e.c == 992
h.a == e.a : True
h.b == e.b : False
h.c == e.c : False
In a sense the set of attributes of an object also form a namespace.
http://docs.python.org/2/tutorial/classes.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With