python中导入的类的作用域是什么?
时间:2020-03-06 14:33:39 来源:igfitidea点击:
请原谅含糊不清的标题。如果有人有建议,请告诉我!另外,请使用更合适的标签重新标记!
问题
我希望有一个导入类的实例,以便能够查看导入器范围内的内容(全局,本地)。由于我不确定在这里工作的确切机制,因此我可以用摘要而不是文字来更好地描述它。
## File 1 def f1(): print "go f1!" class C1(object): def do_eval(self,x): # maybe this should be do_evil, given what happens print "evaling" eval(x) eval(x,globals(),locals())
然后从一个迭代会话运行此代码,将会有很多NameErrors
。
## interactive class C2(object): def do_eval(self,x): # maybe this should be do_evil, given what happens print "evaling" eval(x) eval(x,globals(),locals()) def f2(): print "go f2!" from file1 import C1 import file1 C1().do_eval('file1.f1()') C1().do_eval('f1()') C1().do_eval('f2()') file1.C1().do_eval('file1.f1()') file1.C1().do_eval('f1()') file1.C1().do_eval('f2()') C2().do_eval('f2()') C2().do_eval('file1.f1()') C2().do_eval('f1()')
这类任务是否有共同的习惯用法/模式?我是否完全将错误的树吠叫?
解决方案
函数总是在它们定义的范围内执行,方法和类主体也是如此。它们永远不会在另一个范围内执行。因为导入只是另一个赋值语句,而Python中的所有内容都是引用,所以函数,类和模块甚至都不知道将它们导入到何处。
我们可以做两件事:明确传递我们希望他们使用的"环境",或者使用堆栈黑客访问其调用者的名称空间。前者比后者更受青睐,因为它不像后者那样依赖于实现且脆弱。
我们可能希望看一下string.Template类,它试图做类似的事情。
在这个例子中,我们可以简单地将函数作为对象移交给C1中的方法:
>>> class C1(object): >>> def eval(self, x): >>> x() >>> >>> def f2(): print "go f2" >>> c = C1() >>> c.eval(f2) go f2
在Python中,我们可以将函数和类传递给其他方法,然后在其中调用/创建它们。
如果我们想实际评估代码字符串,则必须指定环境,如Thomas所提到的。
模块从上面稍作更改:
## File 1 def f1(): print "go f1!" class C1(object): def do_eval(self, x, e_globals = globals(), e_locals = locals()): eval(x, e_globals, e_locals)
现在,在交互式解释器中:
>>> def f2(): >>> print "go f2!" >>> from file1 import * # 1 >>> C1().do_eval("f2()") # 2 NameError: name 'f2' is not defined >>> C1().do_eval("f2()", globals(), locals()) #3 go f2! >>> C1().do_eval("f1()", globals(), locals()) #4 go f1!
一些注释
- 在这里,我们将
file1
中的所有对象插入到该模块的名称空间中 - f2不在file1的命名空间中,因此我们得到一个NameError。
- 现在我们明确地通过了环境,可以对代码进行评估
- f1位于此模块的名称空间中,因为我们已导入它
编辑:添加了有关如何显式传递eval环境的代码示例。