Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python闭包中的数值变量范围(Python v2.5.2)_Python - Fatal编程技术网

Python闭包中的数值变量范围(Python v2.5.2)

Python闭包中的数值变量范围(Python v2.5.2),python,Python,我有一个嵌套函数,试图访问在父作用域中分配的变量。从next()函数的第一行,我可以看到path和节点\u done按预期分配距离、当前和左概率没有值,导致抛出名称错误 我做错了什么?如何从next()函数访问和修改current、distance和probability\u left的值 def cheapest_path(self): path = [] current = 0 distance = 0 nodes_done = [False for _ in

我有一个嵌套函数,试图访问在父作用域中分配的变量。从
next()
函数的第一行,我可以看到
path
节点\u done
按预期分配<代码>距离、
当前
左概率
没有值,导致抛出
名称错误

我做错了什么?如何从
next()
函数访问和修改
current
distance
probability\u left
的值

def cheapest_path(self):
    path = []
    current = 0
    distance = 0
    nodes_done = [False for _ in range(len(self.graph.nodes))]
    probability_left = sum(self.graph.probabilities)

    def next(dest):
        log('next: %s -> %s distance(%.2f), nodes_done(%s), probability_left(%.2f)' % (distance,self.graph.nodes[current],self.graph.nodes[dest],str(nodes_done),probability_left))
        path.append((current, distance, nodes_done, probability_left))

        probability_left -= self.graph.probabilities[current]
        nodes_done[current] = True
        distance = self.graph.shortest_path[current][dest]
        current = dest

    def back():
        current,nodes_done,probability_left = path.pop()

按照Python嵌套作用域的工作方式,您永远不能将变量赋值给父作用域中的变量,除非它是全局变量(通过
global
关键字)。这在Python3中发生了变化(添加了
非本地的
),但在2.x中,您将陷入困境

相反,您必须使用通过引用存储的数据类型对此进行排序:

def A():
    foo = [1]
    def B():
        foo[0] = 2 # since foo is a list, modifying it here modifies the referenced list
请注意,这就是列表变量工作的原因-它们是通过引用存储的,因此修改列表会修改原始引用的列表。如果您试图在嵌套函数中执行类似于
path=[]
的操作,那么它将不起作用,因为这实际上是分配给
path
(Python会将其解释为在嵌套函数中创建一个新的局部变量
path
,该嵌套函数会隐藏父函数的
路径

有时使用的一个选项是将所有要持久化的内容保留在
dict
中的嵌套范围中:

def A():
    state = {
        'path': [],
        'current': 0,
        # ...
    }

    def B():
        state['current'] = 3

简而言之,python没有适当的词法范围支持。如果是这样的话,就必须有更多的语法来支持该行为(即使用var/def/my关键字来声明变量范围)

除了实际的词法范围之外,您最好将数据存储在环境数据结构中。一个简单的例子是列表,例如:

def cheapest_path(self):
    path = []
    path_info = [0, 0]
    nodes_done = [False for _ in range(len(self.graph.nodes))]
    probability_left = sum(self.graph.probabilities)

    def next(dest):
        distance, current = path_info
        log('next: %s -> %s distance(%.2f), nodes_done(%s), probability_left(%.2f)' %     (distance,self.graph.nodes[current],self.graph.nodes[dest],str(nodes_done),probability_left))
        path.append((current, distance, nodes_done, probability_left))

        probability_left -= self.graph.probabilities[current]
        nodes_done[current] = True
        path_info[0] = self.graph.shortest_path[current][dest]
        path_info[1] = dest

    def back():
        current,nodes_done,probability_left = path.pop()

你可以这样做,也可以检查魔法。有关此操作的更多历史信息,请阅读此内容。

如果您碰巧正在使用Python 3,则可以使用
非本地
语句()使这些变量存在于当前范围中,例如:

def next(dest):
    nonlocal distance, current, probability_left
    ...

+1.在这种情况下,为了清楚起见,我建议使用一个
dict
,而不是一个列表。@Cameron我实际上只是添加了一个注释:PI认为可能是这样的,但要确保我没有遗漏语言中的某些内容这是不正确的:
nonlocal
关键字允许在外部但非全局范围内写入变量。不幸的是,它只在Python3中可用,这有点令人费解,因为我认为这纯粹是一个语法问题,甚至不需要额外的VM支持;但它就在那里。它确实需要向后移植到2.x,因为在大多数人使用3.x之前还需要几年时间;因此,给出适用于该版本的答案通常是有意义的。您还需要修改
probability\u left
。此外,最好使用
dict
而不是列表,因为
[0]
[1]
的描述性远远低于
['current']
['distance']