在Python中访问调用函数的变量

时间:2013-03-25 06:34:34

标签: python python-3.x

我怀疑我想做的事情在Python中不是那么干净。以下是一些相互调用的嵌套函数。 (通常,它们不必是词法范围的,但需要动态地相互调用。)

def outer() :
    s_outer = "outer\n"

    def inner() :
        s_inner = "inner\n"
        do_something()

    inner()

现在,当我调用do_something()时,我想在callstack的更上方访问调用函数的变量,在本例中为s_outers_inner

不幸的是,nonlocal关键字只有在do_something()函数中定义inner()时才能帮助我。但是,如果我将其定义为与outer()相同的级别,则nonlocal关键字将无效。

但是,我想从各种其他函数中调用do_something(),但始终在各自的上下文中执行它并访问它们各自的范围。

感觉顽皮然后我写了一个小的访问者,我可以在do_something()内调用这样的访问者:

def reach(name) :
    for f in inspect.stack() :
        if name in f[0].f_locals : return f[0].f_locals[name]
    return None 

然后

def do_something() :
    print( reach("s_outer"), reach("s_inner") )

工作正常。

我的两个问题是这些

  1. 有没有更好的方法来解决这个问题? (除了将相应的数据包装成dicts并将这些dicts明确地传递给do_something()

  2. 是否有更优雅/更短的方式来实施reach()功能?

  3. 干杯!

3 个答案:

答案 0 :(得分:4)

没有,在我看来,应该没有优雅的方式来实现reach,因为这引入了一个非常难以理解,调试,测试和维护的新的非标准间接。正如Python口头禅(试试import this)所说:

  

明确比隐含更好。

所以,只需传递参数即可。从今天起,你将来会非常感激你。

答案 1 :(得分:2)

我最终做的是

scope = locals()

并从scope访问do_something。这样我就无需访问,但我仍然可以访问调用者的局部变量字典。这非常类似于自己构建字典并传递它。

答案 2 :(得分:1)

  

有没有更好的方法来解决这个问题? (除了将相应的数据包装成dicts并将这些dicts明确地传递给do_something())

明确传递dicts是一种更好的方法。

你提出的建议听起来非常不同寻常。当代码大小增加时,您必须将代码分解为模块化体系结构,并在模块之间使用干净的API。它还必须易于理解,易于解释,并且易于交给另一个程序员来修改/改进/调试它。您提出的建议听起来像一个干净的API,非常规,具有非明显的数据流。我怀疑它可能会让许多程序员在看到它时变得脾气暴躁。 :)

另一个选择是使函数成为类的成员,数据在类实例中。如果您的问题可以建模为在数据对象上运行的多个函数,那么这可能会很好。