访问变量

问题描述:

假设我有以下函数返回一个函数:访问变量

def make_square_matrix_creator(dim): 

    mat = np.zeros([dim, dim]) 

    def square_matrix_creator(value): 
     mat += value 
     return mat 
    return square_matrix_creator 

现在,这个代码不起作用,因为内部函数不能访问mat

f = make_square_matrix_creator(4) 

f(3) 

UnboundLocalError: local variable 'mat' referenced before assignment 

我知道有几种方法可以解决这个问题;我可以让mat全球:

def make_square_matrix_creator(dim): 

    global mat 
    mat = np.zeros([dim, dim]) 

    def square_matrix_creator(value): 
     global mat 
     mat += value 
     return mat 
    return square_matrix_creator 

它的工作原理,但是这一切与职能范围内使全局对象相关的问题

我可以通过垫作为默认参数传递给内部函数;

def make_square_matrix_creator(dim): 

    mat = np.zeros([dim, dim]) 

    def square_matrix_creator(value, mat=mat): 
     mat += value 
     return mat 
    return square_matrix_creator 

但是,当我在我的真实世界的例子中尝试了这一点,我遇到了可变默认值的问题。是否有其他选项可以让内部函数访问在其父函数中创建的对象?

+0

使用'nonlocal' .. – styvane

+0

如果您正在使用Python 3.x中,你可以看看[外地](https://docs.python.org/3/reference/simple_stmts.html#grammar- token-nonlocal_stmt)语句。 –

+0

我使用Python 2.7 - 我将编辑我的问题 –

对于Python 2.7,您可以使用[:]来指示嵌套函数中的就地变异。示例 -

def make_square_matrix_creator(dim): 
    mat = np.zeros([dim, dim]) 
    def square_matrix_creator(value): 
     mat[:] = mat + value 
     return mat 
    return square_matrix_creator 

我在Python 3.4测试了这(可悲的是,我没有一个Python 2.7使用numpy的对它进行测试,我在Python 2.7测试正常列表,它工作正常的列表)。演示 -

In [50]: def make_square_matrix_creator(dim): 
    ....:   mat = np.zeros([dim, dim]) 
    ....:   def square_matrix_creator(value): 
    ....:     mat[:] = mat + value 
    ....:     return mat 
    ....:   return square_matrix_creator 
    ....: 

In [53]: f = make_square_matrix_creator(4) 

In [54]: f(3) 
Out[54]: 
array([[ 3., 3., 3., 3.], 
     [ 3., 3., 3., 3.], 
     [ 3., 3., 3., 3.], 
     [ 3., 3., 3., 3.]]) 

您可以尝试创建一个别名。

# This class is a minimally working shim for the numpy object 
# because I don't want to import the full numpy package. 
class K(object): 
    def __init__(self, other): 
     self.v = other 

    def __iadd__(self, other): 
     self.v += other 

def outer(x): 
    mat = K(x) 
    def inner(y): 
     alias = mat # Create alias to mutable object. alias is now modifiable 
     alias += 1 # Modify alias to work around Python 2.x limitation. 
     return mat 
    return inner 

>>> f = outer(5) 
>>> res = f(1) 
>>> res 
<__main__.K at 0x102acb1d0> 
>>> res.v 
6 
>>> f(1) 
<__main__.K at 0x102acb1d0> 
>>> res.v 
7