在Python中轻松地从/向名称空间/词典转储变量

Ame*_*ina 10 python syntax dictionary nested

说我有在Python几个变量或对象a,b,c,...

如何轻松地这些变量转储到Python中的命名空间中并在以后恢复它们?(例如,以相同的方式argparse将各种变量包装到命名空间中).

以下是我希望如何在命名空间之间转储内容的两个示例:

将局部变量转储到命名空间中

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
Run Code Online (Sandbox Code Playgroud)

从命名空间转储局部变量e

# 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
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是:这在Python中是否可行?(注意,该方法dump_into_namespace不直接接收变量的名称,至少就我所知).

如果上面的答案是否定的,我怎么能用这样的界面呢?

e = dump_into_namespace('a', 'b', 'c')
Run Code Online (Sandbox Code Playgroud)

此外,如何使用字典而不是命名空间来完成此操作?

有一些线程似乎与动态定义变量的点访问相关,但我不认为它们解决了转储变量的问题:

是否有任何库通过点表示法来促进此类访问?

更新:

看起来有一个库支持Python中的点可访问字典,称为Bunch,但我不确定它是否会像我定义的那样支持轻松转储.

pio*_*kuc 6

下面的解决方案提供的语法非常接近您的要求,唯一的区别是您必须传递给明确定义变量的函数环境:

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
Run Code Online (Sandbox Code Playgroud)

然后,您可以将变量"转储"回本地(例如,在不同的函数中):

>>> locals().update(o.vars)
>>> x
10
Run Code Online (Sandbox Code Playgroud)

编辑:

由于eyquem的建议,这可以更短.我们的想法是将变量放入self.__dict__'dump'对象(注意:更新的语法在这里更改):

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 5

您可以通过多种方法创建"命名空间".最简单的两个是:

  • 创建一个快速自定义类:

    class Namespace(object):
        def __init__(self, **kw):
            self.__dict__.update(kw)
    
    def dump_into_namespace(**kw):
        return Namespace(**kw)
    
    Run Code Online (Sandbox Code Playgroud)

    打电话给dump_into_namespace(a='a', b='b', c='c'); 这需要任意数量的关键字参数.

  • 使用collections.namedtuple课程:

    from collections import namedtuple
    
    Namespace = namedtuple('Namespace', 'a b c')
    
    def dump_into_namespace(a, b, c):
        return Namespace(a, b, c)
    
    Run Code Online (Sandbox Code Playgroud)

    打电话给dump_into_namespace('a', 'b', 'c'); 这只需要固定数量的参数,但您的dump_into_namespace()函数可以提供默认值.

你所谓的'点符号'实际上只是属性访问.