首页 > 编程 > Python > 正文

详解python中的 is 操作符

2020-02-16 11:18:59
字体:
来源:转载
供稿:网友

大家可以与Java中的 == 操作符相互印证一下,加深一下对引用和对象的理解。原问题: Python为什么直接运行和在命令行运行同样语句但结果却不同,他们的缓存机制不同吗?

其实,高票答案已经说得很详细了。我只是再补充一点而已。

is 操作符是Python语言的一个内建的操作符。它的作用在于比较两个变量是否指向了同一个对象。

与 == 的区别

class A(): def __init__(self, v):   self.value = v def __eq__(self, t):   return self.value == t.valuea = A(3)b = A(3)print a == bprint a is b

这个结果是True,False。因为我们重写了__eq__方法就使得a, b在比较的时候,只比较它们的value即可。只要它们的value相等,那么a, b就是相等的。

而 is 操作符是判断两个变量是否引用了同一个对象。

同一个对象?

is 的用法说起来其实挺简单的,但是真正用起来,它的难点恰恰就在于判断哪些对象是同一个对象。

看下面的几个测试,先不看结果,自己能答对多少?

a = 10b = 10print a is ba = 10.0b = 10.0print a is ba = 10def f(): return 10print f() is aa = 1000def f(): return 1000print f() is aa = 10.0def f(): return 10.0print f() is a

嗯。这个结果是True, True, True, False, False。你答对了吗?

这个结果中牵扯到两个问题:第一,就是小整数的缓存,第二,就是pyc文件中CodeObject的组织问题。

Python中把-127到128这些小整数都缓存了一份。这和Java的Integer类是一样的。所以,对于-127到128之间的整数,整个Python虚拟机中就只有一个实例。不管你什么时候,什么场景下去使用 is 进行判断,都会是True,所以我们知道了这两个测试一定会是True:

a = 10b = 10print a is ba = 10def f(): return 10print f() is a

接着,我们重点看下,这两个测试:

a = 10.0b = 10.0print a is ba = 10.0def f(): return 10.0print f() is a

为什么一个是True,一个是False。要探究这个问题,就要从字节码的角度去分析了。我们先把这个文件编译一下:

python -m compileall testis.py

然后再使用这个工具查看一下字节码文件: 

  https:// github.com/hinus/railgu n/blob/master/src/main/python/rgparser/show.py

得到这样的输出:

 <argcount> 0 </argcount> <nlocals> 0</nlocals> <stacksize> 2</stacksize> <flags> 0040</flags> <code>  6400005a00006400005a01006500006501006b080047486400005a000064  01008400005a02006502008300006500006b0800474864020053 </code> <dis> 1   0 LOAD_CONST    0 (10.0)    3 STORE_NAME    0 (a) 2   6 LOAD_CONST    0 (10.0)    9 STORE_NAME    1 (b) 3   12 LOAD_NAME    0 (a)    15 LOAD_NAME    1 (b)    18 COMPARE_OP    8 (is)    21 PRINT_ITEM       22 PRINT_NEWLINE   5   23 LOAD_CONST    0 (10.0)    26 STORE_NAME    0 (a) 6   29 LOAD_CONST    1 (<code object f>)    32 MAKE_FUNCTION   0    35 STORE_NAME    2 (f) 8   38 LOAD_NAME    2 (f)    41 CALL_FUNCTION   0    44 LOAD_NAME    0 (a)    47 COMPARE_OP    8 (is)    50 PRINT_ITEM       51 PRINT_NEWLINE      52 LOAD_CONST    2 (None)    55 RETURN_VALUE   </dis> <names> ('a', 'b', 'f')</names> <varnames> ()</varnames> <freevars> ()</freevars> <cellvars> ()</cellvars> <filename> 'testis.py'</filename> <name> '<module>'</name> <firstlineno> 1</firstlineno> <consts>  10.0  <code>   <argcount> 0 </argcount>   <nlocals> 0</nlocals>   <stacksize> 1</stacksize>   <flags> 0043</flags>   <code> 64010053</code>   <dis> 7   0 LOAD_CONST    1 (10.0)    3 RETURN_VALUE     </dis>   <names> ()</names>   <varnames> ()</varnames>   <freevars> ()</freevars>   <cellvars> ()</cellvars>   <filename> 'testis.py'</filename>   <name> 'f'</name>   <firstlineno> 6</firstlineno>   <consts>   None   10.0   </consts>   <lnotab> 0001</lnotab>  </code>  None </consts> <lnotab> 060106010b0206010902</lnotab>            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表