2010-04-07 72 views
2

我显然在对Python范围的理解很差的情况下工作。也许你可以帮忙。“库”方法的范围

背景:
我使用

if __name__ == "__main__" 

结构来我模块(S)在执行 “自检”。每次自测都会调用各种公共方法,并在开发模块时打印结果以进行视觉检查。

为了保持 “普尔蒂” 和可管理的,我创建了一个小方法来简化方法的调用测试:

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

foo = "bar" 

与调用pprint_vars:

pprint_vars('foo') 

打印:

foo = 'bar' 

一切都很好。

问题陈述:
不开心,只是吻,我有脑小雨动我的方便,花花公子“pprint_vars”的方法到一个名为“debug_tools.py”一个单独的文件,只需输入“debug_tools”每当我想访问'pprint_vars'。

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

import debug_tools 

foo = bar 
debug_tools.pprint_vars('foo') 

继续工作它的魔力和打印:

foo = 'bar' 

相反,它招呼我:

NameError: name 'some_var' is not defined 

非理性的信念:
我相信(显然是错误的)该导入会将输入方法(或多或少)与代码“内联”,因此变量范围规则将保持类似于如果方法我们重新定义内联。

请求帮助:
有人可以纠正我对误区的理解吗?

感谢, JS

+0

你确定你发布了完全相同的代码吗?它不应该是'foo ='bar''吗?我找不到错误信息中提到的'some_var'。 – 2010-04-07 23:39:14

+0

你是对的,菲利克斯。我很抱歉。我有(希望)纠正错误。 – 2010-04-07 23:49:06

+0

'__name__'成语通常写成'if __name__' =='__main__“:',测试是否相等。它正好使用了__in__运算符,因为它包含了测试,但有些意外。 – Todd 2010-04-08 02:30:01

回答

2

在Python中的每个文件是它自己的命名空间。一个函数被调用时,解析它的变量以下列顺序:

  1. 局部变量(包括捕获的变量或在封闭)
  2. (模块)的全局变量
  3. 建宏

您可以使用(解释器特定的)inspect模块作为框架列表导航调用堆栈。由于框架知道它的当地人,全局,建宏和父框架,你可以“看”的解释,通过呼叫方这样的眼(请仅用于调试):

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

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

+0

作为实现我的目标的首选方式,您会有什么建议? – 2010-04-07 23:41:47

+0

使用各种'检查。* frame *()'函数获取调用者的框架,然后访问框架的'f_locals'属性以获取本地:'inspect.getouterframes(inspect.currentframe())[1] [0] .f_locals [var_in] ' – 2010-04-07 23:52:59

0

EVAL接受两个可选参数 - 全球当地 - 你可以指定为背景来评价你的源:

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

如果'var_in'应该位于完全不同的未知模块中,这将无济于事。 – 2010-04-07 23:57:48

1

我会推荐路过的当地人()的功能,像这样......

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

...

pprint_var(var_name, locals()) 

,如果你不希望出现这种情况,你可以使用检查模块或sys._getframe做同样的事情,正如其他人所暗示的那样d。

0

我遇到的基本问题是Python对于简单对象没有名称的意义。对于方法,类等等,对于简单的对象,没有。

因此,在这种特征变量的语言,我的“ppvar”功能会是这个样子(伪代码):

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

我可以导入该文件包含的任何工程“ppvar”,并把它和它基本上会被“内联”到我的代码中。

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

所有语言都有优缺点。每种语言都有一些“简单”的东西。能够执行如下操作:

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

在Python中是(至今)不是可行的。好吧。