大家可以与Java中的 == 操作符相互印证一下,加深一下对引用和对象的理解。原问题: Python为什么直接运行和在命令行运行同样语句但结果却不同,他们的缓存机制不同吗"color: #ff0000">与 == 的区别
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
得到这样的输出:
<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>
大家注意看,整个python文件其实就是一个大的<code>对象,f 所对应的那个函数也是一个<code>对象,这个code对象做为整体是大的<code>对象的consts域里的一个const项。再注意,在大<code>对象里,有10.0这样的一个const项,f 这个<code>对象所对应的conts里呢,也有一个10.0这个浮点数。
当python在加载这个文件的时候,就会完成主<code>里的10.0这个浮点数的加载,生成一个PyFloatObject。也就是说静态的pyc文件的常量表在被加载以后,就变成了内存中的常量表,文件的表里的10.0就变成了内存中的一个PyFloatObject。所以,a, b两个变量都会引用这个PyFloatObject。
但是 f 里的那个10.0呢?它是要等到MAKE_FUNCTION被调用的时候才会真正地初始化。做为 f 方法的返回值,它必然与我们之前所说的主<code>里的10.0不是同一个对象了。
本质上讲,这是Python的一个设计缺陷(例如Java以一个文件为编译单元,共享同一个常量池就会减轻这个问题。但如果跨文件使用 == 操作符,也会出现同样的问题。仍然没有解决这个问题。实际上,我自己也不知道该怎么解决这个问题。)我们应该尽量避免 is 的这种用法。始终把 is 的用法限制在本文的第一个例子中。这样相对会安全一些。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】