Python中的变量

什么是变量?

Python变量与C或C ++中的变量根本不同。事实上,Python甚至没有变量。Python有名称,而不是变量。

这可能看起来很迂腐,而且大多数情况下都是如此。大多数时候,将Python名称视为变量是完全可以接受的,但理解差异很重要。当您在Python中实现棘手的指针时尤其如此。

为了帮助推动差异,可以了解变量如何在C中工作,它们代表什么,然后将其与名称在Python中的工作方式进行对比。

C中的变量

假设您有以下代码来定义变量x:

int  x  =  2337 ;

这一行代码在执行时有几个不同的步骤:

为整数分配足够的内存

将值分配2337给该内存位置

指示x指向该值

以简化的内存视图显示,它可能如下所示:

c_memory1.jpg

X的内存表示(2337)

在这里,您可以看到该变量x具有伪内存位置0x7f1和值2337。如果在程序中稍后要更改其值x,则可以执行以下操作:

x  =  2338 ;

上面的代码为2338变量分配了一个新的value()x,从而覆盖了以前的值。这意味着变量x是可变的。更新的内存布局显示新值:

c_memory2.jpg

X的新内存表示(2338)

请注意,位置x没有改变,只是值本身。这是一个重要的观点。这意味着它x 是内存位置,而不仅仅是它的名称。

另一种思考这个概念的方法是在所有权方面。从某种意义上说,x拥有内存位置。x首先,它是一个空盒子,它可以恰好适合一个可以存储整数值的整数。

为值分配值时x,您将在所x拥有的框中放置一个值。如果你想引入一个新的变量(y),你可以添加这行代码:

int  y  =  x ;

此代码创建一个名为的新框y,并将值复制x到框中。现在内存布局将如下所示:

c_memory3.jpg

X(2338)和Y(2338)的内存表示

注意新的位置0x7f5的y。即使将值x复制到y,变量也会y在内存中拥有一些新地址。因此,您可以覆盖y不影响的值x:

y  =  2339 ;

现在内存布局将如下所示:

c_memory4.jpg

更新了Y(2339)的代表

同样,你修改的值y,但不是它的位置。此外,您根本没有影响原始x变量。这与Python名称的工作方式形成鲜明对比。

Python中的名称

Python没有变量。它有名称。是的,这是一个迂腐点,你当然可以随意使用术语变量。重要的是要知道变量和名称之间存在差异。

让我们从上面的C示例中获取等效代码并将其写在Python中:

>>> x  =  2337

与C类似,上面的代码在执行过程中分解为几个不同的步骤:

创建一个 PyObject

将typecode设置为整数 PyObject

将值设置2337为PyObject

创建一个名为 x

指向x新的PyObject

增加的引用计数PyObject被1

注意:这PyObject与Python不同object。它特定于CPython并表示所有Python对象的基本结构。

PyObject被定义为C结构,所以,如果你想知道为什么你不能打电话typecode或refcount直接,其因为你没有进入结构直接。方法调用sys.getrefcount()可以帮助获得一些内部。

在内存中,它可能看起来像这样:

py_memory1.jpg

Python的内存中表示(2337)

您可以看到内存布局与之前的C布局截然不同。新创建的Python对象拥有生命中的内存,而不是x拥有值2337所在的内存块2337。Python名称x不像C变量在内存中拥有静态插槽那样直接拥有任何内存地址x。

如果您尝试为其分配新值x,可以尝试以下操作:

>>> x  =  2338

这里发生的事情与C等价物不同,但与Python中的原始绑定没有太大区别。

这段代码:

创建一个新的 PyObject

将typecode设置为整数 PyObject

设置值2338的PyObject

点x新PyObject

将new的refcount增加PyObject1

将旧的refcount减少PyObject1

现在在内存中,它看起来像这样:

py_memory2.jpg

Python名称指向新对象(2338)

此图有助于说明x指向对象的引用,并且不像以前那样拥有内存空间。它还显示该x = 2338命令不是赋值,而是将名称绑定x到引用。

此外,前一个对象(持有该2337值)现在位于内存中,引用计数为0,并将被垃圾收集器清理。

您可以y在C示例中引入一个新名称:

>>> y  =  x

在内存中,您将拥有一个新名称,但不一定是新对象:

py_memory3_1.jpg

X和Y名称指向2338

现在,你可以看到一个新的Python对象没有被创建,只是指向同一个对象的新名称。此外,对象的refcount增加了一个。您可以检查对象标识是否相同,以确认它们是否相同:

>>> y is x
True

上面的代码表明x和y是相同的对象。不过没错:y它仍然是不可改变的。

例如,您可以执行以下操作y:

>>> y += 1
>>> y is x
False

添加调用后,将返回一个新的Python对象。现在,内存看起来像这样:

py_memory4.jpg

x name和y命名不同的对象

已创建新对象,y现在指向新对象。有趣的是,这是如果你已经绑定到的最终状态y,以2339直接:

>>> y  =  2339

上述语句导致与添加相同的结束内存状态。回顾一下,在Python中,您不需要分配变量。而是将名称绑定到引用。

【Python中的对象】

来源:PY学习网:原文地址:https://www.py.cn/article.html