最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解python中的 is 操作符

 更新時(shí)間:2017年12月26日 13:57:12   作者:海納  
is 操作符是Python語言的一個(gè)內(nèi)建的操作符。它的作用在于比較兩個(gè)變量是否指向了同一個(gè)對象。下面通過本文給大家詳細(xì)介紹python中的 is 操作符,需要的朋友參考下吧

大家可以與Java中的 == 操作符相互印證一下,加深一下對引用和對象的理解。原問題: Python為什么直接運(yùn)行和在命令行運(yùn)行同樣語句但結(jié)果卻不同,他們的緩存機(jī)制不同嗎?

其實(shí),高票答案已經(jīng)說得很詳細(xì)了。我只是再補(bǔ)充一點(diǎn)而已。

is 操作符是Python語言的一個(gè)內(nèi)建的操作符。它的作用在于比較兩個(gè)變量是否指向了同一個(gè)對象。

與 == 的區(qū)別

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

這個(gè)結(jié)果是True,F(xiàn)alse。因?yàn)槲覀冎貙懥薩_eq__方法就使得a, b在比較的時(shí)候,只比較它們的value即可。只要它們的value相等,那么a, b就是相等的。

而 is 操作符是判斷兩個(gè)變量是否引用了同一個(gè)對象。

同一個(gè)對象?

is 的用法說起來其實(shí)挺簡單的,但是真正用起來,它的難點(diǎn)恰恰就在于判斷哪些對象是同一個(gè)對象。

看下面的幾個(gè)測試,先不看結(jié)果,自己能答對多少?

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

嗯。這個(gè)結(jié)果是True, True, True, False, False。你答對了嗎?

這個(gè)結(jié)果中牽扯到兩個(gè)問題:第一,就是小整數(shù)的緩存,第二,就是pyc文件中CodeObject的組織問題。

Python中把-127到128這些小整數(shù)都緩存了一份。這和Java的Integer類是一樣的。所以,對于-127到128之間的整數(shù),整個(gè)Python虛擬機(jī)中就只有一個(gè)實(shí)例。不管你什么時(shí)候,什么場景下去使用 is 進(jìn)行判斷,都會(huì)是True,所以我們知道了這兩個(gè)測試一定會(huì)是True:

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

接著,我們重點(diǎn)看下,這兩個(gè)測試:

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

為什么一個(gè)是True,一個(gè)是False。要探究這個(gè)問題,就要從字節(jié)碼的角度去分析了。我們先把這個(gè)文件編譯一下:

python -m compileall testis.py

然后再使用這個(gè)工具查看一下字節(jié)碼文件: 

  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>

大家注意看,整個(gè)python文件其實(shí)就是一個(gè)大的<code>對象,f 所對應(yīng)的那個(gè)函數(shù)也是一個(gè)<code>對象,這個(gè)code對象做為整體是大的<code>對象的consts域里的一個(gè)const項(xiàng)。再注意,在大<code>對象里,有10.0這樣的一個(gè)const項(xiàng),f 這個(gè)<code>對象所對應(yīng)的conts里呢,也有一個(gè)10.0這個(gè)浮點(diǎn)數(shù)。

當(dāng)python在加載這個(gè)文件的時(shí)候,就會(huì)完成主<code>里的10.0這個(gè)浮點(diǎn)數(shù)的加載,生成一個(gè)PyFloatObject。也就是說靜態(tài)的pyc文件的常量表在被加載以后,就變成了內(nèi)存中的常量表,文件的表里的10.0就變成了內(nèi)存中的一個(gè)PyFloatObject。所以,a, b兩個(gè)變量都會(huì)引用這個(gè)PyFloatObject。

但是 f 里的那個(gè)10.0呢?它是要等到MAKE_FUNCTION被調(diào)用的時(shí)候才會(huì)真正地初始化。做為 f 方法的返回值,它必然與我們之前所說的主<code>里的10.0不是同一個(gè)對象了。

本質(zhì)上講,這是Python的一個(gè)設(shè)計(jì)缺陷(例如Java以一個(gè)文件為編譯單元,共享同一個(gè)常量池就會(huì)減輕這個(gè)問題。但如果跨文件使用 == 操作符,也會(huì)出現(xiàn)同樣的問題。仍然沒有解決這個(gè)問題。實(shí)際上,我自己也不知道該怎么解決這個(gè)問題。)我們應(yīng)該盡量避免 is 的這種用法。始終把 is 的用法限制在本文的第一個(gè)例子中。這樣相對會(huì)安全一些。

相關(guān)文章

最新評論

博爱县| 临桂县| 磐石市| 兴山县| 永兴县| 锦州市| 汾阳市| 洛川县| 全州县| 盘锦市| 沙坪坝区| 弥勒县| 丰顺县| 临西县| 乐安县| 赤城县| 新野县| 洛川县| 天镇县| 齐河县| 前郭尔| 洞头县| 绥阳县| 磐安县| 平武县| 甘肃省| 若尔盖县| 广州市| 三台县| 镇康县| 读书| 宣化县| 巨鹿县| 赤峰市| 黄骅市| 拜泉县| 永春县| 云霄县| 鱼台县| 德州市| 莱阳市|