3.25
今天遇到了这样一个问题:
1 | class ListNode: |
可见,a.set()
并没有改变a的值,不得其解
看了这篇文章
豁然开朗,之前理解有误的原因是自动把C++的赋值与Python混淆了
Python的变量,其实是C++意义上的指针
下面摘录几段:
构造函数返回指针
Python 的构造函数将构造匿名对象,且返回此对象的一个指针。
这是 Python 与指针的第一个重要联系。
用代码描述,对于Python代码:
1 | sampleNum = 0 |
其不类似于 C++ 代码:
1 | int sampleNum = 0; |
而更类似于:
1 | int __tmpNum = 0, *sampleNum = &__tmpNum; |
__setitems__操作将隐式解指针
Python 与指针的另一个重要联系在于 Python 的隐式解指针行为。
虽然 Python 不存在显式解指针操作,但(有且仅有)__setitems__操作将进行隐式解指针,通过此方法对变量进行修改等同于通过解指针操作修改变量原值。
此种性质意味着:
- 任何不涉及__setitems__的操作都将成为指针重绑定。
对于Python代码:
1 | numList = [None] * 10 |
其相当于:
1 | int *numList = new int[10]; |
由此可见,对 numList 的非__setitems__操作,导致 numList 被绑定到了一个新指针上。
- 任何涉及__setitems__的操作都将成为解指针操作。
由于 Python 对哈希表的高度依赖,“涉及__setitems__的操作”在 Python 中实际上是一个非常广泛的行为,这主要包括:
- 对数组的索引操作
- 对哈希表的查找操作
- 涉及__setattr__的操作(由于 Python 将 attribute 存储在哈希表中,所以__setattr__操作最终将是某种__setitems__操作)
于是,将set()
改为这样:
1 | def set(self, L): |
就解决了问题
self
是默认将实例本身传入的参数,根据上文,实际传入的是实例的指针,而self=ListNode(val=L[0])
将self
重新绑定至一个新建的节点,那么后续进行的操作就与原实例无关了