2

网络中的 python 名称存在很多混淆,并且文档似乎对名称并没有那么清楚。以下是我读到的关于 python 名称的几件事。

  1. 名称是对对象的引用(它们在哪里?堆?)并且名称包含的是地址。(如Java)。

  2. python 中的名称就像 C++ 引用 (int& b),这意味着它是内存位置的另一个别名;即对于int a,a是一个内存位置。ifint& b = a表示这b是同一内存位置的另一个名称

  3. 名称与 C 中自动取消引用的指针变量非常相似。

以上哪些说法是/正确的?

Python 名称中是否包含某种地址,还是只是内存位置的名称(如 C++&引用)?

python名称存储在哪里,堆栈还是堆?

EDIT

从http://etutorials.org/Programming/Python.+Text+processing/Appendix+A.+A+Selective+and+Impressionistic+Short+Review+of+Python/A.2+Namespaces+查看以下行和+绑定/#

每当一个(可能是限定的)名称出现在赋值的右侧,或者单独出现在一行上时,该名称就会被取消引用到对象本身。如果名称尚未绑定在某个可访问范围内,则无法取消引用;尝试这样做会引发 NameError 异常。如果名称后跟左括号和右括号(它们之间可能有逗号分隔的表达式),则在取消引用后调用/调用对象。对于 Python 对象,可以控制和覆盖调用时发生的确切情况;但一般来说,调用函数或方法会运行一些代码,调用类会创建一个实例。例如:

pkg.subpkg.func() # 从命名空间调用函数

x = y # deref 'y' 并将同一个对象绑定到 'x'

这是有道理的。只是想交叉检查它的真实性。请评论和回答

4

3 回答 3

4

名称是对对象的引用

是的。如果您只想了解 Python 变量的语义,则不必关心对象的位置;它们位于内存中,Python 实现为您管理内存。他们如何做到这一点取决于实现(CPython、Jython、PyPy ...)。

python 中的名称就像 C++ 引用

不完全是。在 C++ 中重新分配引用实际上会重新分配所引用的内存位置,例如在

int i = 0;
int &r = i;
r = 1;

确实如此i == 1。除非使用可变容器对象,否则您无法在 Python 中执行此操作。最接近 C++ 参考行为的是

i = [0]   # single-element list
r = i     # r is now another reference to the object referenced by i
r[0] = 1  # sets i[0]

与 C 中自动取消引用的指针变量非常相似

不,因为在上述方面它们类似于 C++ 引用。

Python 名称中是否包含某种地址,还是只是内存位置的名称?

前者更接近事实,假设一个简单的实现(同样,PyPy 的做事可能与 CPython 不同)。在任何情况下,Python 变量都不是存储位置,而是可能存在于内存中任何位置的对象的标签/名称。

Python 进程中的每个对象都有一个可以使用该函数获取的标识id,在 CPython 中该函数返回其内存地址。您可以通过检查两个变量(或更一般的表达式)是否引用同一个对象id,或者更直接地使用is

>>> i = [1, 2]
>>> j = i       # a new reference
>>> i is j      # same identity?
True
>>> j = [1, 2]  # a new list
>>> i == j      # same value?
True
>>> i is j      # same identity?
False
于 2012-09-08T09:40:15.583 回答
2

Python 名称就是名称。你有对象和名字,就是这样。

创建一个对象,比如说在堆的某个地方[3, 4, 5]创建一个对象。你不需要知道怎么做。现在,您可以通过将名称分配给名称来定位此对象:

x = [3, 4, 5]

也就是说,赋值运算符分配名称而不是值。x 不是 [3, 4, 5],不,它只是一个指向[3, 4, 5]对象的名称。所以这样做:

x = 1

不会更改原始[3, 4, 5]对象,而是将对象分配给1名称 x。另请注意,大多数表达式都喜欢[3, 4, 5], 但也会8 + 3创建临时变量。除非您为该临时文件指定名称,否则它将立即死亡。没有(除了,例如在 CPython 中用于小数字,但除此之外)机制来保持未被引用的对象活动并缓存它们。例如,这会失败:

>>> x = [3, 4, 5]
>>> x is [3, 4, 5] # must be some object, right? no!
False

但是,这只是赋值(在 Python 中不可重载)。事实上,Python 中的对象和名称表现得非常好,就像自动取消引用指针一样,除了它们会自动进行引用计数,并且在不再引用之后就会消失(至少在 CPython 中)并且它们不会在分配时自动取消引用。

由于这种内存模型,例如重载索引操作的 C++ 方式不起作用。相反,Python 使用__setitem__and__getitem__因为你不能返回任何“可赋值”的东西。此外,运算符+=,*=等...通过创建临时变量并将该临时变量分配回名称来工作。

于 2012-09-08T09:51:11.467 回答
1

Python 对象存储在堆上,并通过引用计数进行垃圾收集。

变量是对 Java 中对象的引用,因此第 1 点适用。我不熟悉 C++ 或 C 中自动取消引用的指针变量,无法调用它们。

最终,python 解释器负责查找解释器结构中的项目,这些结构通常是 python 列表和字典以及其他此类抽象容器;例如,命名空间使用dict(哈希表),其中名称和值是指向其他 python 对象的指针。这些由映射协议明确管理。

对于python程序员来说,这一切都是隐藏的;你不需要知道你的对象在哪里,只要你有引用它们的东西,它们就仍然活着。在 python 中编码时,您会传递这些引用。

于 2012-09-08T09:38:50.563 回答