【问题标题】:Accessing variables defined in external function from internal function [duplicate]从内部函数访问外部函数中定义的变量
【发布时间】:2015-10-13 16:46:19
【问题描述】:

假设我有以下函数返回一个函数:

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

它可以工作,但这存在与在函数中创建全局对象相关的所有问题

我可以将 mat 作为默认参数传递给内部函数;

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

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

【问题讨论】:

标签: python python-2.7 closures


【解决方案1】:

对于 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 中对此进行了测试(遗憾的是,我没有带有 numpy 的 Python 2.7 来测试它,我在 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.]])

【讨论】:

    【解决方案2】:

    您可以尝试创建别名。

    # 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-29
      • 2013-08-16
      • 2017-05-25
      • 2011-04-15
      • 2021-08-20
      • 2020-03-03
      • 2012-12-31
      • 1970-01-01
      相关资源
      最近更新 更多