当前位置: 首页 > 面试题库 >

Python3的多个赋值和内存地址

江阳夏
2023-03-14
问题内容

我仍然无法理解以下行为:

a = 257
b = 257
print(a is b) #False
a, b = 257, 257
print(a is b) #True

在打印时id(a)id(b)我可以看到在单独的行中为其分配了值的变量具有不同的id,而在进行多次分配时,两个值都具有相同的id:

a = 257
b = 257
print(id(a)) #139828809414512
print(id(b)) #139828809414224
a, b = 257, 257
print(id(a)) #139828809414416
print(id(b)) #139828809414416

但是不可能通过说相同值的多次赋值总是创建指向相同id的指针来解释此行为,因为:

a, b = -1000, -1000  
print(id(a)) #139828809414448
print(id(b)) #139828809414288

是否有明确的规则来解释变量id何时相同以及何时不相同?

编辑

相关信息:此问题中的代码以交互方式运行(ipython3)


问题答案:

这是由于字节码编译器中的不断折叠优化。当字节码编译器编译一批语句时,它使用字典来跟踪所看到的常量。该字典自动合并所有等效常量。

这是负责记录和编号常量(以及一些相关职责)的例程:

static int
compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
{
    PyObject *t, *v;
    Py_ssize_t arg;

    t = _PyCode_ConstantKey(o);
    if (t == NULL)
        return -1;

    v = PyDict_GetItem(dict, t);
    if (!v) {
        arg = PyDict_Size(dict);
        v = PyInt_FromLong(arg);
        if (!v) {
            Py_DECREF(t);
            return -1;
        }
        if (PyDict_SetItem(dict, t, v) < 0) {
            Py_DECREF(t);
            Py_DECREF(v);
            return -1;
        }
        Py_DECREF(v);
    }
    else
        arg = PyInt_AsLong(v);
    Py_DECREF(t);
    return arg;
}

您会看到,如果找不到已经存在的等效常量,它只会添加一个新条目并分配一个新数字。(该_PyCode_ConstantKey位确保喜欢的东西0.0-0.0以及0被认为是不等价的。)

在交互模式下,每次解释器必须实际运行您的命令时,批处理都会结束,因此在命令之间通常不会发生常量折叠:

>>> a = 1000
>>> b = 1000
>>> a is b
False
>>> a = 1000; b = 1000 # 1 batch
>>> a is b
True

在脚本中,所有顶级语句都是一批,因此发生了更多的恒定折叠:

a = 257
b = 257
print a is b

在脚本中,将打印True

函数的代码与函数外部的代码分开跟踪其常量,这限制了常量折叠:

a = 257

def f():
    b = 257
    print a is b

f()

即使在脚本中,也会打印出来False



 类似资料:
  • 我使用的是MAX144 ADC,数据表中没有提供有关读取ADC值的控制寄存器的信息。我使用STM32L452RE微控制器和SPI从ADC获取数据。ADC的数据表如下: https://datasheets.maximintegrated.com/en/ds/MAX144-MAX145.pdf 遇到相同问题的任何人请指导。 我的想法是为SPI RX创建一个2字节的缓冲区,并在其中存储值。但是我不知道

  • 对同一变量多次赋值在C++里是合法的,这一点之前并没有多说。第二次赋值的效果是用新值替换掉旧值。 int fred = 5; cout << fred; fred = 7; cout << fred; 这段代码输出57,因为第一次打印fred时,其值是5;第二次打印时其值为7。 这种多次赋值的机制正是我把变量形容为值的容器的原因。在为变量赋值时,修改的是容器里的内容,如图所示: 当存在对同一变量

  • 本文向大家介绍Python3多目标赋值及共享引用注意事项,包括了Python3多目标赋值及共享引用注意事项的使用技巧和注意事项,需要的朋友参考一下 Python中多目标赋值即将等号左边所有的变量名都赋值给右边的对象,完成赋值操作,比如将三个变量同时赋值给一个字符串。 示例结果: Python Python Python 在多目标赋值中,其本质即类似三个变量的指针指向了同一个内存空间,即三个变量共享

  • 问题内容: 我知道您可以在JavaScript中执行以下操作: 其中变量将在第一表达式的值,如果它不是,或。在这种情况下,它将被分配给第二条语句的值。 但是,当我们使用逻辑AND运算符时,变量将分配给什么? 非假的时候会发生什么?假的 时候会发生什么? 只是学习JavaScript,我很好奇结合AND运算符的赋值会发生什么。 问题答案: 基本上,逻辑与运算符(),将返回第二操作数的值,如果第一个是

  • 编程最简单的算法之一,莫过于变量交换。交换变量的常见算法需要一个中间变量进行变量的临时保存。用传统方法编写变量交换代码如下: 在计算机刚发明时,内存非常“精贵”。这种变量交换往往是非常奢侈的。于是计算机“大牛”发明了一些算法来避免使用中间变量: 这样的算法很多,但是都有一定的数值范围和类型要求。 到了Go语言时,内存不再是紧缺资源,而且写法可以更简单。使用 Go 的“多重赋值”特性,可以轻松完成变

  • 问题内容: (不用担心,这不是关于拆开元组的另一个问题。) 在python中,类似这样的语句将变量foo,bar和baz分配给5。它可以从左到右分配这些变量,这可以通过诸如nastier的例子来证明 但是python语言参考指出赋值语句具有以下形式 并在分配时首先评估,然后进行分配。 那么,如果不是,该行如何有效?如何解析和评估一行上的这些多个分配?我阅读的语言参考书是否错误? 问题答案: 所有功