10

Pythonにいくつかの変数またはオブジェクトがあるとしましょうa、、、、b.. c..

これらの変数をPythonの名前空間に簡単にダンプし、後で復元するにはどうすればよいですか?(たとえば、同じ方法でargparseさまざまな変数を名前空間にラップします)。

名前空間との間で物事をダンプする方法の2つの例を次に示します。

ローカル変数を名前空間にダンプする

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

名前空間からのローカル変数のダンプ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

私の最初の質問は:これはPythonでまったく可能ですか?dump_into_namespace(少なくとも私が知る限り、メソッドは変数の名前を直接受け取らないことに注意してください)。

上記の答えが「いいえ」の場合、このようなインターフェースでどのように行うことができますか?

e = dump_into_namespace('a', 'b', 'c')

また、名前空間の代わりに辞書を使用してこれをどのように行うのでしょうか?

動的に定義された変数のドットアクセスに対処することに関連すると思われるスレッドがいくつかありますが、変数のダンプの問題に対処しているとは思いません。

も参照してください

ドット表記を介してこのタイプのアクセスを容易にするライブラリはありますか?

アップデート:

Pythonでドットアクセス可能な辞書をサポートするBunchというライブラリがあるようですが、定義したとおり、簡単にダンプできるかどうかはわかりません。

4

4 に答える 4

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

次に、変数をローカルに「ダンプ」して戻すことができます(たとえば、別の関数で)。

>>> locals().update(o.vars)
>>> x
10

編集:

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
于 2013-02-15T21:44:56.177 に答える
5

'名前空間'を作成するためのいくつかのオプションがあります。最も簡単な2つは次のとおりです。

  • 簡単なカスタムクラスを作成します。

    class Namespace(object):
        def __init__(self, **kw):
            self.__dict__.update(kw)
    
    def dump_into_namespace(**kw):
        return Namespace(**kw)
    

    で呼び出す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)
    

    で呼び出すdump_into_namespace('a', 'b', 'c'); これは固定数の引数のみを取りますが、dump_into_namespace()関数はデフォルトを提供できます。

「ドット表記」と呼ばれるのは、実際には単なる属性アクセスです。

于 2013-02-15T21:31:43.093 に答える
4

正直なところ、最も簡単な方法は、それらを割り当てることです。

e.a = a
e.b = b
e.c = c

変数はそれ自体の名前を知らないため、実際にはこれ以上動的に行うことはできません。それらをキーワード引数として渡す必要があります。その場合、名前空間を__dict__直接更新できます。

def dump_into_namespace(e, **kwargs):
    e.__dict__.update(kwargs)

そして、あなたはそれを次のように呼ぶ必要があります:

dump_into_namespace(e, a=a, b=b, c=c)
于 2013-02-15T21:32:58.627 に答える
2

編集:

piokucの答えは、私に環境を考慮に入れるように促しました

私のソリューションはself._dict_を更新するため、特別な関数を定義する必要はありません__getattr__関数に渡されるオブジェクトは実際の属性になり、その名前は作成されたオブジェクトのディクショナリに属します。

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

結果

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

ある意味で、オブジェクトの属性のセットも名前空間を形成します。

http://docs.python.org/2/tutorial/classes.html

于 2013-02-15T22:07:38.560 に答える