2015-10-13 170 views
0

假設我有以下函數返回一個函數:訪問變量

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 - 我將編輯我的問題 –

回答

0

對於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.]]) 
0

您可以嘗試創建一個別名。

# 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