2017-07-31 36 views
0

我有一个超类的自初始化实例有条件进口,但子类不能看到该模块(Python的2.7):子类__init__没有看到超conditonally导入模块

class A(object): 
    def __init__(self, arg1): 
     self.attr1 = self.method1(arg1) 

    def method1(self, arg1): 
     if arg1 == 'foo': 
      import amodule 
      return amodule.method1() 
     else: 
      return 'not a dependency on foo' 


class B(A): 
    def __init__(self, arg1): 
     super(B, self).__init__(arg1) 
     if arg1 == 'foo': 
      self.attr2 = self.method2(self.attr1) 

    def method2(self, attr1): 
     return amodule.method2() 

if __name__=='__main__': 
    b = B("foo") 
    print b.attr2 

这将引发NameError: global name 'amodule' is not defineda = A("foo")工程就好了

在这种情况下,super调用是否应该执行import amodule? (并且使用import应该将模块置于全局模式?)

+1

'amodule'是*局部变量*。你为什么会认为你可以在'method2'中访问它?另外,'import'语句不会在全局名称空间中绑定模块名称,而是在任何名称空间中绑定import语句。再次,这将是* local1到'method1' *。 –

+0

不会将当前正在执行的模块的全局名称空间导入add/amodule /? (\_\_主要\_\_)? – cowbert

+1

不,它不会自己检查这个'def f():import sys',然后调用'f()'看看sys是否在全局命名空间中,它不是(除非它已经)。 –

回答

2

是否不将add/amodule /导入到当前执行模块 的全局名称空间? (__main__)?

没有,模块添加到sys.modules但如果是在本地进口的,那么你将不会有任何引用了。即名称amodule现在不见了。

,您仍然可以访问使用sys.modules模块:

def method2(self, attr1): 
    import sys 
    return sys.modules['amodule'].method2() 

或者你可以再次使用import amodule导入它,它会从sys.modules有所回升。


# Here b.py contains 
# print('Module b was imported') 

def func1(): 
    print('inside func1') 
    import b 

def func2(): 
    print('inside func2') 
    import sys 
    print(sys.modules['b']) 
    import b 


def func3(): 
    print('inside func3') 
    import b 
    import sys 
    print('Deleted b') 
    del sys.modules['b'] 
    import b 


func1() 
print() 
func2() 
print() 
func3() 

演示:

inside func1 
Module b was imported 

inside func2 
<module 'b' from '/Users/ashwini/py/b.py'> 

inside func3 
Deleted b 
Module b was imported 
+0

我也可以将它作为一个实例对象。不幸的是,导入这个模块有点贵。 – cowbert

+1

@cowbert这些计算只会在第一次导入时发生,之后的导入将会选择已导入的模块,除非您从'sys.modules'中删除它。检查答案中的示例。 –

0

尝试将import amodule放在程序的第一行。

原因是amodule是在method1中导入的,method2没有访问权限。

+0

导入是有条件的,因为没有提到的具体原因(因为它与手头的问题无关)。 – cowbert

0

如果你按照你的代码,你会看到你没有达到method1()。

当你创建对象 b = B(foo) 你去通过A. 初始化()监守呼吁超()。但是,您的init类A()不包含任何导入语句。然后A.__init__部分完成,并且您继续B.__init__()。下一个命令是对amodule对象的调用,它根本没有被导入。

您可以添加一个辅助方法,它检查arg是否等于'Foo',如果是,则导入模块。然后在A.__init__()函数中添加对此函数的调用。

另一个说明,__init__()工作是初始化变量。它不应该返回任何东西。

+0

A. \ _ \ _ init \ _ \ _()调用A.method1()... – cowbert

+0

你在哪里看到\ _ \ _ init _ _ _ _()返回任何东西?它会初始化变量,它们的初始值应该是内部方法的返回值... – cowbert