Python:在封闭范围内赋值之前引用的自由变量'numpy'

时间:2012-11-13 04:15:40

标签: python

我正在将一些代码添加到现有类中以进行测试。通常,此类eigensystem_CUDA_implementation依赖于其父级的某些功能和属性。当这个类独立于程序的其余部分导入时,我想用普通的父类替换testParent类。

如果这是测试代码的一种不好的方法,我应该完全不同地做到这一点,我对这个建议持开放态度。

初始化eigensystem_CUDA_implementation对象时,错误为:

  

NameError:在封闭范围

中赋值之前引用的自由变量'np'

追溯到行self.mat = np.matrix(...

还有更多依赖于eigensystem_CUDA_implementation中未显示的NumPy和pyCUDA。类可以导入它依赖的模块吗?由于第一个错误,尚未对此进行测试。

class eigensystem_CUDA_implementation:
    def __init__(self, parent = None, max_time = 60, delta = 10**(-32)):
            # For testing purposes, when class is utilized independently
            if(not parent):
                    # testing mode
                    if(not sys.modules.has_key("numpy")):
                            import numpy as np
                            import pycuda.driver as cuda
                            import pycuda.autoinit
                            from pycuda.compiler import SourceModule
                    class testParent:
                            def __init__(self, size = 10):
                                    self.size = size
                                    self.delta = 10**(-32)
                                    self.num_site_types = 8
                                    self.mat =  np.matrix(np.random.random((self.size,self.size)).astype(np.float64))
                            def get_mutation_selection_matrix(self, alpha):
                                    return self.mat
    ...

一个潜在的问题:not sys.modules.has_key("numpy")会将NumPy显示为已导入,无论其名称为“np”还是其他内容。其余的代码使用“np”,所以我忽略了这一点。

感谢您的任何建议

2 个答案:

答案 0 :(得分:3)

如果已导入numpy,您的代码将失败。您只能在if块内导入它,因此如果它已经导入,则不会在该块内定义。但是稍后在同一个函数中,您将np作为局部变量引用。

无论如何,你真的不必担心导入numpy。只要无条件地import numpy as np。如果已导入,则只会重新使用导入的版本。它不会浪费内存或任何导入它的东西两次。

那就是说,这段代码看起来相当笨拙和脆弱。您应该看看是否有更好的方法,例如通过定义一个单独的函数来修补具有必要属性的类。在另一个类中的方法内部有一个类和一个导入变得非常毛茸茸。

答案 1 :(得分:1)

当您在函数中放置导入时,就像您在__init__中所做的那样,模块被赋予的变量是该函数的本地变量。如果您希望它是一个全局变量,您需要使用global语句明确地使用它。 global np, cuda, SourceModule可能会这样做。

此外,在使用numpy之前检查sys.modules中的np可能还不够,因为numpy可能已由其他模块而非当前模块导入。您可以检查np in locals(),但可以更容易地无条件地执行导入。