将对象属性设置为python中方法中使用的每个变量

时间:2013-02-07 18:24:02

标签: python reflection

如何将(几乎)对象方法中的所有局部变量设置为该对象的属性?

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

2 个答案:

答案 0 :(得分:0)

受到Python update object from dictionary的启发,我想出了以下内容:

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

答案 1 :(得分:-1)

已经有python debugger允许您检查局部变量,因此使用随机实例属性污染对象没有意义。

如果多个方法使用相同的局部变量名,您的方法也不起作用,因为方法可能会覆盖某些实例属性,使对象的状态处于模糊状态。

此外,您的解决方案违反了DRY principle,因为您必须在每return之前添加代码。

另一个缺点是,在方法执行期间,您通常想要在多个位置知道局部变量的状态,这对您的答案是不可能的。

如果你真的想手动保存本地变量,那么这样的事情可能比你的解决方案好得多:

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调试器。