-1

オブジェクトのメソッド内の (ほぼ) すべてのローカル変数をそのオブジェクトの属性に設定するにはどうすればよいですか?

class Obj(object):
    def do_something(self):
        localstr = 'hello world'
        localnum = 1
        #TODO store vars in the object for easier inspection

x = Obj()
x.do_something()
print x.localstr, x.localnum
4

2 に答える 2

0

Dictionary のPython update オブジェクトに触発されて、次のように思いつきました。

class Obj(object):
    def do_something(self):
        localstr = 'hello world'
        localnum = 1

        # store vars in the object for easier inspection
        l = locals().copy()
        del l['self']
        for key,value in l.iteritems():
            setattr(self, key, value)

x = Obj()
x.do_something()
print x.localstr, x.localnum
于 2013-02-07T18:24:01.857 に答える
-1

ローカル変数を検査できるPython デバッガーは既に存在するため、オブジェクトをランダムなインスタンス属性で汚染しても意味がありません。

また、メソッドがインスタンス属性の一部を上書きし、オブジェクトの状態があいまいな状態のままになる可能性があるため、複数のメソッドが同じローカル変数名を使用する場合、このアプローチは機能しません。

また、すべての前にコードを追加する必要があるため、ソリューションはDRY 原則returnに反します。

もう1つの欠点は、メソッドの実行中に複数の場所でローカル変数の状態を知りたいことがよくあることですが、これはあなたの答えでは不可能です。

ローカル変数を手動で保存したい場合は、おそらく次のような方法が解決策よりもはるかに優れています。

import inspect
from collections import defaultdict



class LogLocals(object):

    NO_BREAK_POINT = object()

    def __init__(self):
        self.__locals = defaultdict(defaultdict(list))

    def register_locals(self, local_vars, method_name=None, 
                              break_point=NO_BREAK_POINT):
        if method_name is None:
            method_name = inspect.currentframe(1).f_code.co_name
        self.__locals[method_name][break_point].append(local_vars)

    def reset_locals(self, method_name=None, break_point=NO_BREAK_POINT,
                           all_=False):
        if method_name is None:
            method_name = inspect.currentframe(1).f_code.co_name
        if all_:
            del self.__locals[method_name]
        else:
            del self.__locals[method_name][point]

    def get_locals(self, method_name, break_point=NO_BREAK_POINT):
        return self.__locals[method_name][break_point]

それを継承してregister_locals(locals())、状態を保存したいときに呼び出すだけです。また、「ブレークポイント」を区別することもできます。最も重要なことは、インスタンスを汚染しないことです。listまた、最後の状態ではなく状態を返すさまざまな呼び出しを区別します。

属性を介していくつかの呼び出しのローカルにアクセスしたい場合は、次のように簡単に実行できます。

class SimpleNamespace(object):  # python3.3 already provides this
    def __init__(self, attrs):
        self.__dict__.update(attrs)

the_locals = x.get_locals('method_1')[-1]   # take only last call locals
x = SimpleNamespace(the_locals)
x.some_local_variable

とにかく、これはあまり役に立たないと思います。Python デバッガーを使用する必要があります。

于 2013-02-08T08:48:58.907 に答える