“图书馆”方法的范围

时间:2010-04-07 23:33:39

标签: python import module scope

我显然是在对Python范围很差的理解下工作。也许你可以帮忙。

背景:
我正在使用

if __name__ == "__main__"

构造在我的模块中执行“自我测试”。每次自我测试都会调用各种公共方法,并在开发模块时打印其结果以进行可视化检查。

为了保持“清晰”和易于管理,我创建了一个简化方法调用测试的小方法:

def pprint_vars(var_in):
    print("%s = '%s'" % (var_in, eval(var_in)))

foo = "bar"

用:

调用pprint_vars
pprint_vars('foo')

打印:

foo = 'bar'

一切都很好。

问题陈述:
不高兴只是KISS,我有脑子毛毛雨将我方便的'pprint_vars'方法移动到一个名为'debug_tools.py'的单独文件中,只要我想要访问'pprint_vars'就导入'debug_tools'。

这就是事情崩溃的地方。我希望

import debug_tools

foo = bar
debug_tools.pprint_vars('foo')

继续发挥其魔力并打印:

foo = 'bar'

相反,它迎接我:

NameError: name 'some_var' is not defined

不合理的信念:
我相信(显然是错误地)导入将导入的方法(或多或少)与代码“内联”,因此如果方法是内联定义的,变量范围规则将保持相似。

请求帮助:
有人可以纠正我对进口范围的理解(错误)吗?

谢谢, JS

5 个答案:

答案 0 :(得分:2)

“全局范围”在Python中实际上并不存在。通常所谓的“全局范围”实际上是模块范围。也就是说,在模块级定义的名称。将该函数放在另一个模块中意味着它的模块范围会发生变化。

答案 1 :(得分:2)

在python中,每个文件都是自己的命名空间。调用函数时,按以下顺序解析其变量:

  1. 局部变量(包括捕获的变量或在闭包中)
  2. (模块)全局变量
  3. 建宏
  4. 您可以使用(特定于解释器)inspect模块将callstack导航为帧列表。由于框架知道它的本地,全局,内置和父框架,你可以通过你的调用者的眼睛“看到”解释器(请仅用于调试):

    import inspect
    def log_var(name):
        f = inspect.currentframe().f_back
        if name in f.f_locals:
            print "local `%s` = %r" % (name, f.f_locals[name])
        elif name in f.f_globals:
            print "global `%s` = %r" % (name, f.f_globals[name])
        elif name in f.f_builtins:
            print "builtin `%s` = %r" % (name, f.f_builtins[name])
        else:
            print "`%s` not found" % name
    

答案 2 :(得分:1)

我建议将locals()传递给函数,就像这样......

def pprint_var(var_name, D):
    print "%s = %r" % (var_name, D[var_name])

...

pprint_var(var_name, locals())

如果你不想这样,你可以使用inspect模块或sys._getframe来做同样的事情,正如其他人所建议的那样。

答案 3 :(得分:0)

eval 接受两个可选参数 - 全局本地 - 您可以将其指定为评估来源的上下文:

print("%s = '%s'" % (var_in, eval(var_in, globals())))

答案 4 :(得分:0)

我遇到的基本问题是Python对简单对象没有 name 的感觉。对于方法,类等,是的,对于简单对象,没有。

所以在具有变量的语言中,我的'ppvar'函数看起来像这样(伪代码):

ppvar( var_name ):
    print("%s = '%s'", var_name, $var_name)

我可以在任何项目中导入包含'ppvar'的文件并调用它,它基本上会“内联”到我的代码中。

唉,这很可能是一个“函数式编程”概念,不适合面向对象的方法。

所有语言都有优点和缺点。每种语言都有一些“简单”的东西。能够执行以下内容:

print("%s = '%s'" % (var.__name__, var)
Python中的

(截至目前)并不适用。哦,好吧。