Python的语义

12 浏览
0 Comments

Python的语义

为什么在Python中以下代码表现出意外行为?

>>> a = 256
>>> b = 256
>>> a is b
True           # 这是预期的结果
>>> a = 257
>>> b = 257
>>> a is b
False          # 这里发生了什么?为什么是False?
>>> 257 is 257
True           # 然而,字面数字可以正确比较

我正在使用Python 2.5.2。尝试一些不同版本的Python,似乎Python 2.3.3在99和100之间显示上述行为。

基于上述内容,我可以假设Python内部实现了“小”整数和较大整数的存储方式不同,并且is操作符可以区分它们。为什么会有这种泄漏的抽象?在我事先不知道它们是数字还是其他对象的情况下,有什么更好的方法比较两个任意对象是否相同?

0
0 Comments

Python语义学的问题是由于CPython的实现导致的。在CPython中,处理创建新的int对象的C-API函数是PyLong_FromLong(long v)。函数的描述是:当前的实现在-5和256之间的所有整数之间维护一个整数对象的数组,当你在这个范围内创建一个int对象时,实际上只是得到一个对现有对象的引用。因此,改变1的值应该是可能的。我怀疑Python在这种情况下的行为是未定义的。

为了解决这个问题,我们需要查看CPython的源代码。具体地说,我们需要查看Objects子目录中的longobject.c文件。在这个文件中,我们可以找到处理int对象创建的函数。通过阅读代码,我们了解到,当创建的int在-5和256之间时,实际上只是得到一个对预先分配的对象的引用。这个预先分配的对象存储在small_ints数组中。因此,当你想要创建一个在[NSMALLNEGINTS, NSMALLPOSINTS)范围内的新的int对象时,你将得到一个对已经存在的对象的引用。

另外,当Python进行编译时,如果你有两个匹配的字面量,它会使用相同的PyLongObject来表示它们。这意味着如果你执行257 is 257这个语句,CPython会加载相同的对象,因此is操作符会返回True。

总之,Python语义学问题的出现是由于CPython实现的一些具体细节所导致的。通过查看源代码,我们可以了解到这些细节,并找到解决问题的方法。

0
0 Comments

Python的“is”运算符在比较整数时的行为是否出乎意料?根据Python的官方文档,不应该使用is运算符来比较整数。而应该使用==和!=来分别比较相等和不相等的情况。is运算符用于比较对象的身份是否相同,即两个对象是否是同一个实例。而==运算符用于比较对象的值是否相等。在Python中,整数是不可变的对象,因此它们的值不会改变。使用is运算符来比较整数的身份是没有意义的。

is运算符的使用场景是比较单例对象,比如None。因为None在内存中只有一个实例,可以使用is运算符来判断对象是否为None。但是对于整数、字符串、元组等其他对象,应该使用==运算符来比较值的相等性。

在Python中,整数256的身份是相同的,因此is运算符返回True。而整数257的身份是不同的,因此is运算符返回False。这是因为CPython优化了整数256的内存使用,使得多个变量引用同一个实例,而对于整数257,每次都创建一个新的实例。

虽然is运算符可以用于快速比较对象的身份,但是由于其适用范围有限,一般情况下应该使用==运算符来比较值的相等性。is运算符主要用于判断对象是否为None或者比较单例对象的身份。

对于楼主提到的使用is运算符比较状态机的状态,可以考虑使用枚举类型(Enum)来表示状态。枚举类型可以保证每个状态都是唯一的实例,可以使用is运算符来比较状态的身份。另外,也可以使用其他方式来表示状态,比如使用自定义的类或者使用sentinel对象来表示状态。

需要注意的是,不要将is运算符用于比较浮点数和NaN。浮点数的值可能相同但身份不同,因此使用is运算符比较浮点数的身份是没有意义的。而对于NaN,应该使用特定的函数来判断是否为NaN,而不是使用is运算符。

总之,is运算符主要用于比较对象的身份,适用于判断对象是否为None或者比较单例对象的身份。对于其他情况,应该使用==运算符来比较值的相等性。

0
0 Comments

Python中的这个问题是由于整数对象的语义所引起的。在Python中,整数是对象,每个整数都有一个唯一的标识符(id)。通常情况下,我们认为两个整数对象相等的标准是它们的值相等,但在Python中,整数对象的相等性判断还取决于对象的id是否相等。

在上面的例子中,我们可以看到当a和b的值都是256时,它们的id是相等的,而当a和b的值是257时,它们的id是不相等的。这是因为Python的当前实现在内部维护了一个整数对象的数组,该数组包含了所有数值在-5和256之间的整数对象。当我们创建一个在这个范围内的整数时,实际上只是返回了对已有对象的引用,而不是创建一个新的对象。

这种实现细节的目的是为了提高性能和节省内存。由于整数在编程中经常被使用,特别是在循环和计算中,所以对于常用的整数值,Python通过共享对象的方式来减少内存的使用。

然而,这种实现细节是特定于CPython解释器的,其他Python解释器可能会有不同的实现方式。因此,我们不能依赖于整数对象的id来判断它们的相等性。

解决这个问题的方法是,我们应该始终使用"=="运算符来比较整数对象的值,而不是使用"id()"函数来比较它们的id。这样可以确保代码的可移植性,并且不会受到不同解释器实现的影响。

总结起来,Python中整数对象的语义问题是由于内部实现细节所引起的。为了避免出现这种问题,我们应该使用"=="运算符来比较整数对象的值。这样可以确保代码在不同的Python解释器中都能正确运行。

0