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

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

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

与 == 的区别

class A():

def __init__(self, v):

self.value = v

def __eq__(self, t):

return self.value == t.value

a = A(3)

b = A(3)

print a == b

print a is b

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

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

同一个对象?

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

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

a = 10

b = 10

print a is b

a = 10.0

b = 10.0

print a is b

a = 10

def f():

return 10

print f() is a

a = 1000

def f():

return 1000

print f() is a

a = 10.0

def f():

return 10.0

print f() is a

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

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

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

a = 10

b = 10

print a is b

a = 10

def f():

return 10

print f() is a

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

a = 10.0

b = 10.0

print a is b

a = 10.0

def f():

return 10.0

print f() is a

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

python -m compileall testis.py

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

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

得到这样的输出:

0

0

2

0040

6400005a00006400005a01006500006501006b080047486400005a000064

01008400005a02006502008300006500006b0800474864020053

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 ()

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

('a', 'b', 'f')

()

()

()

'testis.py'

''

1

10.0

0

0

1

0043

64010053

7 0 LOAD_CONST 1 (10.0)

3 RETURN_VALUE

()

()

()

()

'testis.py'

'f'

6

None

10.0

0001

None

060106010b0206010902

大家注意看,整个python文件其实就是一个大的对象,f 所对应的那个函数也是一个对象,这个code对象做为整体是大的对象的consts域里的一个const项。再注意,在大对象里,有10.0这样的一个const项,f 这个对象所对应的conts里呢,也有一个10.0这个浮点数。

当python在加载这个文件的时候,就会完成主里的10.0这个浮点数的加载,生成一个PyFloatObject。也就是说静态的pyc文件的常量表在被加载以后,就变成了内存中的常量表,文件的表里的10.0就变成了内存中的一个PyFloatObject。所以,a, b两个变量都会引用这个PyFloatObject。

但是 f 里的那个10.0呢?它是要等到MAKE_FUNCTION被调用的时候才会真正地初始化。做为 f 方法的返回值,它必然与我们之前所说的主里的10.0不是同一个对象了。

本质上讲,这是Python的一个设计缺陷(例如Java以一个文件为编译单元,共享同一个常量池就会减轻这个问题。但如果跨文件使用 == 操作符,也会出现同样的问题。仍然没有解决这个问题。实际上,我自己也不知道该怎么解决这个问题。)我们应该尽量避免 is 的这种用法。始终把 is 的用法限制在本文的第一个例子中。这样相对会安全一些。

本文标题: 详解python中的 is 操作符

本文地址: http://www.cppcns.com/jiaoben/python/215755.html

python操作符op_详解python中的 is 操作符相关推荐

  1. Python 装饰器详解(中)

    Python 装饰器详解(中) 转自:https://blog.csdn.net/qq_27825451/article/details/84581272,博主仅对其中 demo 实现中不适合pyth ...

  2. python scatter参数详解_Python 中 scatter 函数参数及用法详解

    Python 中 scatter 函数参数及用法详解 Python 中 scatter 函数参数及用法详解 这里有新鲜出炉的 Python 教程, 程序狗速度看过来! Python 编程语言 Pyth ...

  3. python import io_详解Python IO编程

    文件读写 读文件 try: # windows下utf8 f = open('./README.md', 'r', encoding='utf8', errors='ignore') print(f. ...

  4. python流程控制-详解Python流程控制语句

    流程控制 流程:代码执行的过程 控制:对代码执行过程的把控 三大结构 顺序结构:代码默认从上到下,依次执行 分支结构:单项分支,双向分支,多项分支,巢状分支 循环结构:while循环和for循环 单项 ...

  5. python 标准输出_详解Python的标准输入输出

    本篇文章给大家分享的是详解Python的标准输入输出,内容挺不错的,希望可以帮助到有需要的朋友 一.标准输入输出 1.打印到屏幕 产生输出的最简单方法是使用print语句,可以通过用逗号分隔零个或多个 ...

  6. python映射类型-详解Python中映射类型(字典)操作符的概念和使用

    映射类型操作符 (1)标准类型操作符 字典可以和所有的标准类型操作符一起工作,但却不支持像拼接(concatenation)和重复(repetition)这样的操作.这些操作对序列有意义,可对映射类型 ...

  7. python循环语句-详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  8. python数组排序sort_详解python中sort排序使用

    1.前言 昨天一学妹问我一个关于python的问题,当时在外忙碌,没时间细看.今天看一下,咋一看我还真的不知道这个问题,bookinfo.sort(reverse=True ,key=lambda x ...

  9. python scatter参数详解_Python中scatter函数参数及用法详解

    最近开始学习Python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1.scatter函数原型 2.其中散点的形状参数marker如下: 3.其中颜色参数c如 ...

最新文章

  1. 多元回归树分析Multivariate Regression Trees,MRT
  2. oracle视图能增删改,oracle视图的增删改
  3. MediaCodec_loop 崩溃
  4. linux shell 创建序列数组(list,array)方法
  5. tps 数据库写并发衡量_MPP数据库简介
  6. 微信小程序之redirectTo、switchTab和navigateTo
  7. VC实现自定义控件步骤
  8. 7 win 卸载node_node怎么卸载?Windows卸载node方法
  9. 【Java教程系列】JavaSE核心知识点总结
  10. LBRY:美SEC对我们的指控将威胁到整个加密货币行业
  11. View、Bitmap游戏常用
  12. 启动orcal服务和监听的命令的一种方式
  13. 【Visual Assist X】VAssistX的安装和使用
  14. EasyRecovery 15win/mac易恢复序列号
  15. S3存储服务间数据同步工具Rclone介绍
  16. android 增加定时开关机
  17. 我的世界神秘时代研究笔记计算机,我的世界神秘时代5教程全研究笔记连线一览...
  18. angular2项目里使用 Spin(加载中)
  19. 使用python获取微医数据
  20. 【调度】经典作业车间调度问题VS柔性作业车间调度问题

热门文章

  1. 《深入实践Spring Boot》一3.3 使用Thymeleaf模板
  2. 【SQL Sever】将SQL Sever中的一个数据表的数据导出为insert语句
  3. MySQL二进制日志操作
  4. 在tornado里面使用reverse_url
  5. 个人自学ccna的资料+工大瑞普模拟器
  6. CCNA学习与实验指南(640-802)
  7. 大学生经验丨帮助应届生、年轻程序员快速成长的 12 个锦囊妙计!
  8. 老板让我搞数字化转型?成功之后,我整理了这套超全的方法论
  9. 可是笑声太响了的64391111
  10. 程序员怎样获取更多的劳动收入