1

我在一本关于语言描述的书中看到说

On the other hand, a name can be bound to no object (a dangling pointer), 
one object (the usual case), or several objects (a parameter name in a 
 recursive function).

我们如何将名称绑定到多个对象?例如,这不是我们所说的数组,其中所有元素都具有相同的名称但具有索引吗?对于像这里的例子这样的递归函数:

x = 0
def f(y):
    global x
    x += 1
    if x < 4 :
        y +=100
        f(y)

    else: return
f(100)

名称是否y与递归创建的多个值绑定,因为名称表已经将y名称绑定到递归复制的初始值?

已编辑只需按此处Visualizer并查看它生成的内容。:)

4

4 回答 4

6

不,名称绑定到一个对象。当我们谈论 Python 时 - 它要么绑定到给定上下文中的单个对象,要么根本不存在。

发生的情况是,内部工作可能具有在几个“层”中定义的名称 - 但您的代码只会看到其中一个。

如果名称是递归函数中的变量,您将只能在当前运行的上下文中看到绑定到它的内容 - 每次 Python 中有函数调用时,执行框架,它是一个包含多个属性的对象正在运行的代码(包括对局部变量的引用)被冻结。在被调用函数上,创建了一个新的执行框架,并且在那里,变量名再次绑定到它们在被调用上下文中具有的任何新值。您的代码只是“看到”这个实例。

然后,在 Python 中存在全局变量和内置对象的问题:如果名称不是函数执行上下文中的局部变量,则会在全局变量中搜索模块(同样,只有其中一个是可见的) .并且如果名称在全局变量中没有被拒绝,那么 Python 会在 globals().__builtins__您最后一次调用时查找它。

于 2012-10-01T15:58:40.400 回答
3

如果我理解正确,您是在询问 Python 在不同范围内创建变量的规则。Python 在函数级别使用词法作用域

很难准确地说出您编写的代码的目的是什么,但是,虽然y在不同的范围内可能存在不同的值(y在每个递归级别定义的值),但您的代码只会一次只能看到一个(在您操作的范围内定义的值)。

要真正理解 Python 中的范围规则,我会看一下PEP 227。另外,看看这个 Stack Overflow 问题

最后,为了能够聪明地谈论 Python 中的“名称”是什么,我建议您阅读 Python 是如何成为“对象调用”语言的。

在这一点上,我们能够理解,python 不是使用“命名表”,而是使用字典来保存给定范围内可访问的内容。有关更多详细信息,请参阅此答案。这意味着你永远不能在一个范围内拥有两个相同的名称(出于同样的原因,你不能在 python 字典中拥有两个相同的键)。因此,虽然y可能存在于不同范围的字典中,但您无法访问它,因为您只能访问当前范围字典中的变量。

于 2012-10-01T16:01:03.903 回答
0

关键是:

几个对象(递归函数中的参数名称)。

这段话几乎肯定不是指数组,而只是指在递归函数(或任何函数,但递归函数可能一次有多个激活)中,参数可能绑定到不同的值每个递归调用。

这并不意味着您可以访问每个堆栈帧中的每个此类对象;实际上,该技术的重点是确保在每个堆栈帧中只能访问一个这样的值。

于 2012-10-01T16:18:03.130 回答
0

首先,您应该在问题中提到书中的句子与 Python 没有明确的关系(正如 jsbueno 所写,一个名称与 Python 中的一个对象完全绑定)。

无论如何,名称绑定到没有对象有点不准确。通常,名称与变量相关,而与悬空指针相关的名称就是该指针变量的名称。

在谈到变量范围(即使用变量的代码部分)时,一个变量名一次只能用于一个值。但是,可能还有其他代码部分,独立于我们考虑该变量的部分。其他部分代码,可以使用同名;但是,同名的两个变量是完全隔离的。局部变量也是如此,函数体也是如此。如果该语言允许递归,它必须能够创建另一个局部变量的隔离空间,即使对于同一函数的另一个调用也是如此。

在 Python 中,每个函数也可以访问外部变量,但更常见的是使用内部局部变量。每当您为名称分配某个值时,它都会在本地空间中创建。

于 2012-10-01T20:07:15.837 回答