id(t+t), id(t*2)
(42838592, 42838592)
(t+t) is (t*2)
False
如果两个变量指向同一个对象'是',则运算符将返回true。但是第一行表示两者具有相同的id但是'is'运算符给出false值。
答案 0 :(得分:6)
在第一个示例中,您的对象不会在时间上重叠:一个创建然后销毁,然后另一个创建具有相同的ID。
当您将它们与is
进行比较时,您将抓住这两个对象,因此它们会得到不同的ID。
答案 1 :(得分:3)
由Ned Batchelder's answer和the docs for the id
function解释:
两个具有非重叠生命周期的对象可能具有相同的
id()
值。
这两个对象的生命周期不重叠。
他们属于同一元组表达式的事实并没有改变它,因为它不是t+t
和t*2
的元组的一部分,它是id(t+t)
和id(t*2)
。因此,id
返回的这两个整数值具有重叠的生命周期,但传递给id
的参数不会。
了解这一点的一种方法是查看CPython如何编译代码:
>>> dis.dis('id(t+t), id(t*2)')
1 0 LOAD_NAME 0 (id)
2 LOAD_NAME 1 (t)
4 LOAD_NAME 1 (t)
6 BINARY_ADD
8 CALL_FUNCTION 1
10 LOAD_NAME 0 (id)
12 LOAD_NAME 1 (t)
14 LOAD_CONST 0 (2)
16 BINARY_MULTIPLY
18 CALL_FUNCTION 1
20 BUILD_TUPLE 2
22 RETURN_VALUE
所以,这里发生了什么。 (我要为t
选择一个值,比如1000
,只是为了让这更容易理解。)
id
,1000
和1000
被推入堆栈。BINARY_ADD
在位置2000
创建42838592
值。id
会在该值上调用并在位置返回42838592
值,例如42838616
。42838592
值不再存在于堆栈中并且未存储在任何位置,因此id
的参数是对它的唯一引用,因此当它被减少时在功能结束时,它会立即删除。id
,1000
和2
被推入堆栈。BINARY_MULTIPLY
创建一个新的2000
对象。由于位置42838592
刚刚返回到对象池,因此新值将重用该位置。id
会返回另一个42838592
,这次是在42838640
。因此,两个int
值4283592
和4283592
的生命周期重叠(第一个与第二个2000
重叠),两个2000
s不重叠。
最后,请注意,如果t
是一个小数字,
>>> t = 2
>>> (t+t) is (t*2)
True
...因为所有4
值(除非在特殊情况下)都是对同一对象的引用。
同时,如果t
是常量而不是变量,1000+1000 is 1000*2
可能会或可能不会,这取决于您的CPython版本,因为编译单元中的常量折叠的工作方式。
所有这些都表明,试图真正利用两个相等的int
是否是同一个对象,这几乎总是一个可怕的想法。你应该关心这个问题的唯一原因是你是否想要更多地了解CPython的内部结构。
当然这都是CPython特有的。大多数其他Python解释器使用某种形式的垃圾收集器而不是引用计数,因此第一个2000
在创建第二个id
之前不太可能被销毁。另外,并非所有人都使用像CPython这样的对象池。更不用说他们可以为t+t
做完全不同的事情,只要他们可以保证非重叠对象的唯一值。
PyPy实际上通常会在这里返回相同的值 - 但这只是因为它首先将t*2
和t+t
折叠到同一个对象中;尝试使用and you'll get completely different
和t * 3 <label for="category">Category</label>
<select id="categories"
class="form-control"
[formControlName]="category"
value="Select category"
name="category">
<option value="">Select category (skills, interests, locations)</option>
<option *ngFor="let category of categories"
[value]="category.id">{{category.name}}</option>
</select>
id`s。