python - 在 Python 中对不可变对象进行操作时,新对象是如何创建的?
问题描述
我知道不可变对象不能原地更改。创建一个新对象并将其重新分配给相同的变量名称。这样,我们可以保持与变量的关联。在内部,变量指向不同的对象。
>>> string = 'object'
>>> old_id = id(string)
>>> old_id
4452633584
>>> string = 'new' + string
>>> new_id = id(string)
>>> new_id
4501338544
>>> old_id == new_id
False
在上面的示例中,Python 是否创建了一个可变的克隆string
来连接到'new'
,然后在重新分配到 之前使这个新对象不可变string
?
我不明白如何也可以操作无法就地更改的对象。
Python不需要改变一个可改变的东西来产生一个新的东西吗?如果我想把钉子钉在一块木头上,但那块木头是不可改变的,我怎么会得到一块被锤过的木头呢?
解决方案
不变性是语言级别的概念。该语言规定,一旦创建字符串对象,该实现就不会为您提供修改字符串对象的工具。
实现本身可能有内部工具在创建字符串时修改它,然后才能访问它。
例如,在CPython 字符串实现中,字符串连接是通过创建一个PyUnicode
具有新大小的空对象来执行的,该对象在内部表示字符串。然后在返回对象之前复制两个原始字符串中的字符:
PyObject *
PyUnicode_Concat(PyObject *left, PyObject *right)
{
PyObject *result;
/* […] */
Py_ssize_t left_len, right_len, new_len;
/* […] */
left_len = PyUnicode_GET_LENGTH(left);
right_len = PyUnicode_GET_LENGTH(right);
/* […] */
result = PyUnicode_New(new_len, maxchar);
/* […] */
_PyUnicode_FastCopyCharacters(result, 0, left, 0, left_len);
_PyUnicode_FastCopyCharacters(result, left_len, right, 0, right_len);
/* […] */
return result;
}
如果我想把钉子钉在一块木头上,但那块木头是不可改变的,我怎么会得到一块被锤过的木头呢?
在这个类比中,这意味着给你一块木头,里面已经有钉子,但没有给你一把锤子。语言实现已经为您确定了目标,但您不能假设它是如何做到的。它可能使用了锤子,或者它可能在钉子周围长出了一棵树。
推荐阅读
- cluster-analysis - 为 kmeans 聚类分析准备相关数据
- sql - 在 PIVOT SQL 之后未运行第二个选择查询
- report - 如何将 List&Label(通过 Combit)中的数字格式化为幂符号?
- laravel - laravel 中的登录权限
- r - 理解使用 rlang::eval_tidy 时的赋值
- flutter - 如何在 Flutter 的所有页面上显示浮动按钮?
- nuxt.js - 如何在 Nuxt js 中添加一个函数
- python - ValueError:错误的项目数通过 2,位置意味着 1 具有相同的列数
- asp.net - Angular 11:无法从 API 控制器连接到 SQL Server——GET 方法
- javascript - 如何使用javascript在我的计算器上有清除按钮