我显然是在对Python范围很差的理解下工作。也许你可以帮忙。
背景:
我正在使用
if __name__ == "__main__"
构造在我的模块中执行“自我测试”。每次自我测试都会调用各种公共方法,并在开发模块时打印其结果以进行可视化检查。
为了保持“清晰”和易于管理,我创建了一个简化方法调用测试的小方法:
def pprint_vars(var_in):
print("%s = '%s'" % (var_in, eval(var_in)))
当
foo = "bar"
用:
调用pprint_varspprint_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
答案 0 :(得分:2)
“全局范围”在Python中实际上并不存在。通常所谓的“全局范围”实际上是模块范围。也就是说,在模块级定义的名称。将该函数放在另一个模块中意味着它的模块范围会发生变化。
答案 1 :(得分:2)
在python中,每个文件都是自己的命名空间。调用函数时,按以下顺序解析其变量:
您可以使用(特定于解释器)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中的(截至目前)并不适用。哦,好吧。