为什么以下在Python中出现意外行为?
>>> a = 256
>>> b = 256
>>> a is b
True # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False # What happened here? Why is this False?
>>> 257 is 257
True # Yet the literal numbers compare properly
Run Code Online (Sandbox Code Playgroud)
我使用的是Python 2.5.2.尝试一些不同版本的Python,似乎Python 2.3.3显示了99到100之间的上述行为.
基于以上所述,我可以假设Python在内部实现,使得"小"整数以不同于大整数的方式存储,is运算符可以区分.为什么泄漏抽象?当我不知道它们是否是数字时,比较两个任意对象以查看它们是否相同的更好的方法是什么?
Python中的两个变量具有相同的id:
a = 10
b = 10
a is b
>>> True
Run Code Online (Sandbox Code Playgroud)
如果我拿两个lists:
a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False
Run Code Online (Sandbox Code Playgroud)
根据这个链接, Senderle回答说,不可变对象引用具有相同的id,而像列表这样的可变对象具有不同的id.
所以现在根据他的回答,元组应该有相同的ID - 意思是:
a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False
Run Code Online (Sandbox Code Playgroud)
理想情况下,由于元组不可变,它应该返回True,但它正在返回False!
解释是什么?
关于id类型对象的某些东西str(在python 2.7中)让我很困惑.该str类型是不变的,所以我希望,一旦它被创建,它将始终具有相同的id.我相信我不会这么说自己,所以我会发布一个输入和输出序列的例子.
>>> id('so')
140614155123888
>>> id('so')
140614155123848
>>> id('so')
140614155123808
Run Code Online (Sandbox Code Playgroud)
所以同时,它一直在变化.但是,在指向该字符串的变量之后,事情会发生变化:
>>> so = 'so'
>>> id('so')
140614155123728
>>> so = 'so'
>>> id(so)
140614155123728
>>> not_so = 'so'
>>> id(not_so)
140614155123728
Run Code Online (Sandbox Code Playgroud)
因此,一旦变量保存该值,它就会冻结id.的确,在del so和之后del not_so,id('so')开始的输出再次改变.
这是不相同的行为与(小)整数.
我知道不变性和拥有相同之间没有真正的联系id; 仍然,我试图弄清楚这种行为的来源.我相信那些熟悉python内部的人会比我更少惊讶,所以我试图达到同样的目的......
尝试使用不同的字符串会产生不同的结果......
>>> id('hello')
139978087896384
>>> id('hello')
139978087896384
>>> id('hello')
139978087896384
Run Code Online (Sandbox Code Playgroud)
现在它是平等的......
我开始学习Python(python 3.3),我正在尝试is运算符.我试过这个:
>>> b = 'is it the space?'
>>> a = 'is it the space?'
>>> a is b
False
>>> c = 'isitthespace'
>>> d = 'isitthespace'
>>> c is d
True
>>> e = 'isitthespace?'
>>> f = 'isitthespace?'
>>> e is f
False
Run Code Online (Sandbox Code Playgroud)
似乎空间和问号使is行为表现不同.这是怎么回事?
编辑:我知道我应该使用==,我只是想知道为什么is会这样.
我注意到为相同的字符串添加空格使得它们比较不相等is,而非空间版本比较相等.
a = 'abc'
b = 'abc'
a is b
#outputs: True
a = 'abc abc'
b = 'abc abc'
a is b
#outputs: False
Run Code Online (Sandbox Code Playgroud)
我已经阅读了关于将字符串与==和进行比较的问题is.我认为这是一个不同的问题,因为空格字符正在改变行为,而不是字符串的长度.看到:
a = 'abc'
b = 'abc'
a is b # True
a = 'gfhfghssrtjyhgjdagtaerjkdhhgffdhfdah'
b = 'gfhfghssrtjyhgjdagtaerjkdhhgffdhfdah'
a is b # True
Run Code Online (Sandbox Code Playgroud)
为什么在字符串中添加空格会改变此比较的结果?
我想让我的代码更有效(内存).现在我们有很多函数将iterable作为参数,如:
def foo(para,meter,iterable):
#...
pass
Run Code Online (Sandbox Code Playgroud)
有时我们必须提供一个空列表来正常工作:foo(14,25,[]).问题是每次构造一个新列表时:它需要在堆上进行分配,并且列表似乎是64字节的内存(在我自己的机器上,经过测试sys.getsizeof([])),而空元组只需要一个(可能是一次) 48个字节.
因此我想知道空元组是否是一个常数.由于元组是不可变的,因此可以很容易地使元组的长度0(so ())在程序中保持不变.这会减少"构造时间"(因为它只会设置对常量的引用,所以没有)并减少分配的内存量.
我的问题是,对于Python解释器(即任何流行的解释器)是否有保证,空元组确实是一个常量,()因此不需要构造时间也不需要分配额外的内存.
测试它id(..)似乎支持这样的理论:确实只有一个零元组:
>>> id(())
140290183798856
>>> a = ()
>>> id(a)
140290183798856
Run Code Online (Sandbox Code Playgroud)
但有可能在运行时Python解释器出于某种原因分叉元组.
python ×6
identity ×2
operators ×2
python-3.x ×2
tuples ×2
immutability ×1
int ×1
memory ×1
string ×1