如何在python中将名称与多个对象或值绑定

时间:2012-10-01 15:51:44

标签: python binding python-3.x name-binding

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

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 个答案:

答案 0 :(得分:6)

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

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

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

然后,Python中存在全局变量和内置对象的问题:如果名称不是函数执行上下文中的局部变量,则在模块的全局变量中搜索它(再次,只有其中一个将是可见的.ANd如果名称在全局变量中不是defiend,那么,Python会在globals().__builtins__中查找它,这是你的最后一次调用。

答案 1 :(得分:3)

如果我理解正确,你会问到Python在不同scopes中创建变量的规则。 Python在函数级别使用lexical scoping

很难确切地说出你所编写的代码到底是什么,但是,虽然在不同的范围内可能存在与y相关联的不同值(值为y在每个递归级别定义),您的代码将始终只能看到一个(在您运行的作用域中定义的值)。

要真正理解Python中的范围规则,我会看一下PEP 227。另外,请查看this Stack Overflow question

最后,为了能够聪明地谈论Python中的“名称”,我建议您阅读Python是如何使用“Call-By-Object”语言。

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

答案 2 :(得分:0)

关键是:

  

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

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

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

答案 3 :(得分:0)

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

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

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

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