Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python &引用;是";运算符对整数的行为异常_Python_Int_Operators_Identity_Python Internals - Fatal编程技术网

Python &引用;是";运算符对整数的行为异常

Python &引用;是";运算符对整数的行为异常,python,int,operators,identity,python-internals,Python,Int,Operators,Identity,Python Internals,为什么以下内容在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? &g

为什么以下内容在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
我正在使用Python 2.5.2。尝试一些不同版本的Python,Python2.3.3显示了99到100之间的上述行为


基于上述情况,我可以假设Python是在内部实现的,因此“小”整数的存储方式与大整数不同,
is
操作符可以分辨出不同之处。为什么是漏洞百出的抽象?当我事先不知道两个任意物体是否是数字时,有什么更好的方法来比较它们是否相同?

我认为你的假设是正确的。使用
id
(对象标识)进行实验:


看来数字
我认为你的假设是正确的。使用
id
(对象标识)进行实验:

似乎数字
可以看到:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828
以下是我在Python2文档中发现的内容(与此相同):

当前的实现保持了 所有对象的整数对象数组 如果选择-5和256之间的整数 在指定的范围内创建一个int 事实上,只需要回一个参考 现有对象。应该如此 可以更改1的值。我 怀疑Python在中的行为 此案例未定义。:-)

看看这个:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828
以下是我在Python2文档中发现的内容(与此相同):

当前的实现保持了 所有对象的整数对象数组 如果选择-5和256之间的整数 在指定的范围内创建一个int 事实上,只需要回一个参考 现有对象。应该如此 可以更改1的值。我 怀疑Python在中的行为 此案例未定义。:-)


这取决于你是想看两件东西是相等的,还是同一个物体

is
检查它们是否是相同的对象,而不仅仅是相等的对象。为了节省空间,小整数可能指向相同的内存位置

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

您应该使用
==
来比较任意对象的相等性。您可以使用
\uuuu eq\uuuu
\uu ne\uuuu
属性指定行为。

这取决于您查看的是两个事物是否相等,还是相同的对象

is
检查它们是否是相同的对象,而不仅仅是相等的对象。为了节省空间,小整数可能指向相同的内存位置

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144
您应该使用
==
来比较任意对象的相等性。您可以使用
\uuuu eq\uuu
\uu ne\uuu
属性指定行为。

正如您可以签入的那样,Python缓存小整数以提高效率。每次创建对小整数的引用时,都是引用缓存的小整数,而不是新对象。257不是一个小整数,因此它是作为不同的对象计算的

为此,最好使用
=

正如您可以签入的那样,Python缓存小整数以提高效率。每次创建对小整数的引用时,都是引用缓存的小整数,而不是新对象。257不是一个小整数,因此它是作为不同的对象计算的


为此,最好使用
=

对于不可变值对象,如整数、字符串或日期时间,对象标识不是特别有用。最好考虑平等问题。标识本质上是值对象的一个实现细节-因为它们是不可变的,所以对同一个对象或多个对象有多个引用之间没有有效的区别。

对于不可变的值对象,如整数、字符串或日期时间,对象标识不是特别有用。最好考虑平等问题。Identity本质上是值对象的一个实现细节——因为它们是不可变的,所以对同一个对象或多个对象有多个引用之间没有有效的区别。

is
是Identity相等运算符(功能类似于
id(a)==id(b)
);只是两个相等的数字不一定是同一个对象。出于性能原因,一些小整数恰好是相同的,因此它们往往是相同的(这可以做到,因为它们是不可变的)

另一方面,
=
操作符被描述为根据Paulo Freitas的评论检查等式和类型:
x==y和类型(x)==type(y)
。这对于普通数字就足够了,但与以荒谬的方式定义
\uuuu eq\uuu
的类的
is
不同:

class Unequal:
    def __eq__(self, other):
        return False
PHP显然允许“内置”类实现同样的功能(我的意思是在C级实现,而不是在PHP中实现)。稍微不那么荒谬的用法可能是timer对象,它每次用作数字时都有不同的值。这就是为什么您现在要模拟Visual Basic的
,而不是用
time.time()来显示它是一个计算,我不知道

格雷格·休吉尔(Greg Hewgill,OP)发表了一条澄清性评论:“我的目标是比较对象标识,而不是价值相等。除了数字,我希望将对象标识视为价值相等。”

这将有另一个答案,因为我们必须将事物分类为数字或非数字,以选择我们是与
=
比较还是与
比较。定义,包括PyNumber_检查,但这不能从Python本身访问

我们可以尝试将
isinstance
用于我们知道的所有数字类型,但这不可避免地是不完整的。类型模块包含StringTypes列表,但不包含NumberTypes。自Python 2.6以来,内置的数字类有一个基类,但它有相同的问题:

import numpy, numbers
assert not issubclass(numpy.int16,numbers.Number)
assert issubclass(int,numbers.Number)
顺便说一句,将生成单独的低数字实例

我不知道这个问题的答案。我想理论上可以使用ctypes调用
PyNumber\u Check<
>>> a is b
>>> id(a) == id(b)
>>> 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
>>> a is b
>>> id(a) == id(b)
SENTINEL_SINGLETON = object() # this will only be created one time.

def foo(keyword_argument=None):
    if keyword_argument is None:
        print('no argument given to foo')
    bar()
    bar(keyword_argument)
    bar('baz')

def bar(keyword_argument=SENTINEL_SINGLETON):
    # SENTINEL_SINGLETON tells us if we were not passed anything
    # as None is a legitimate potential argument we could get.
    if keyword_argument is SENTINEL_SINGLETON:
        print('no argument given to bar')
    else:
        print('argument to bar: {0}'.format(keyword_argument))

foo()
no argument given to foo
no argument given to bar
argument to bar: None
argument to bar: baz
>>> s = b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)
>>> s = 'somestr'
>>> b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)
>>> s1 = b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, True, 4555308080, 4555308080)

>>> s1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, False, 4555308176, 4555308272)
>>> a = ()
>>> b = ()
>>> a is b
True
>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True
>>> g, h = 42.23e100, 42.23e100
>>> g is h
True
>>> def f(): i, j = 258, 258
>>> dis.dis(f)
  1           0 LOAD_CONST               2 ((128, 128))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (i)
              6 STORE_FAST               1 (j)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480
>>> k, l = (1, 2), (1, 2)
>>> k is l
False
>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True