为什么我应该在 Python 中引用 "names" 和 "binding" 而不是 "variables" 和 "assignment" ?



为什么我应该在Python中引用"名称"one_answers"绑定"而不是"变量"one_answers"赋值"?我知道这个问题有点笼统,但我真的很想知道:)

在C和C++中,变量是一个命名的内存位置。变量的值是存储在该位置的值。指定给变量,然后修改该值。因此,变量是内存位置,而不是它的名称

在Python中,变量是用于引用对象的名称。变量的值就是那个对象。到目前为止听起来还是一样的。但是赋值给变量,你就不会修改对象本身,而是改变变量引用的对象。所以变量是名称,而不是对象。

因此,如果你抽象地考虑Python的属性,或者同时谈论多种语言,那么为这两种不同的东西使用不同的名称是很有用的。为了保持简洁,您可以避免在Python中谈论变量,并将赋值运算符的作用称为"绑定"而不是"赋值"。

请注意,Python语法将"赋值"视为一种语句,而不是"绑定"。至少有一些Python文档调用了名称变量。因此,仅在Python的上下文中,这样做并不是不正确的。术语的不同定义适用于不同的上下文。

例如,在C中,变量是内存中由特定名称标识的位置。例如,int i;表示存在由i标识的4字节(通常)变量。无论是否已为该内存位置分配值,都会分配该内存位置。当C运行i = 1000时,它将存储在存储位置i中的值更改为1000。

在python中,内存的位置和大小与解释器无关。最接近C意义上的"变量"的python是一个值(例如1000),它作为对象存在于内存中的某个位置,无论是否附加名称。通过i = 1000将其绑定到名称。这个命令告诉python创建一个值为1000的整数对象(如果它还不存在),并绑定到名称"i"。一个对象可以很容易地绑定到多个名称,例如:

>>> a = []  # Create a new list object and bind it to the name 'a'
>>> b = a   # Get the object bound to the name 'a' and bind it to the name 'b'
>>> a is b  # Are the names 'a' and 'b' bound to the same object?
True

这解释了术语之间的差异,但只要你理解了差异,你使用哪一个并不重要。除非你迂腐。

我不确定名称/绑定描述是否最容易理解,例如,即使我对Python(尤其是cpython)的工作原理有一定的准确理解,我也一直对此感到困惑。

如果您来自C背景,描述Python如何工作的最简单方法是理解Python中的所有变量实际上都是指向对象的指针,例如list对象实际上是指向值的指针数组。在a = b之后,ab都指向同一对象。

这个简单的Python语义模型似乎有几个棘手的部分失败了,例如list增广运算符+=,但需要注意的是,Python中的a += ba = a + b不一样,但它是一个特殊的增量操作(也可以使用__iadd__方法为用户类型定义;a += b实际上是a = a.__iadd__(b))。

另一件需要理解的重要事情是,尽管在Python中所有变量都是指针,但仍然没有指针概念。换句话说,你不能把"指向变量的指针"传递给函数,这样函数就可以改变变量:C++中的内容是由定义的

void increment(int &x) {
x += 1;
}

或通过在C中

void increment(int *x) {
*x += 1;
}

在Python中无法定义,因为无法传递"变量",只能传递"值"。在Python中传递通用可写位置的唯一方法是使用回调闭包。

谁说你应该这样做?除非您正在讨论与名称绑定操作直接相关的问题;像在任何其他语言中一样,在Python中谈论变量和赋值是非常好的。自然,在不同的编程语言中,精确的含义是不同的。

如果正在调试与"命名和绑定"相关的问题,请使用此术语,因为Python语言引用使用了它:尽可能具体和精确,通过避免不必要的歧义来帮助解决问题。

另一方面,如果你想知道C和Python中的变量之间的区别,那么这些图片可能会有所帮助。

我想说,由于C和Python:之间的一些差异,这种区别是显著的

  1. Duck类型:C变量总是给定类型的实例——在Python中,它不是名称所指的类型可以更改。

  2. 浅拷贝-尝试以下操作:

    >>> a = [4, 5, 6]
    >>> b = a
    >>> b[1] = 0
    >>> a
    [4, 0, 6]
    >>> b = 3
    >>> a
    [4, 0, 6]
    

这是有道理的,因为ab都是名称,它们花费了一些时间绑定到列表实例,而不是单独的变量

最新更新