>> a = "wtf" >>> b = "wtf" >>> a is b True # example2: >>> a = "wtf!" >>> b = "wtf!" >>> a is b False # example3: >>> a , b = "wtf!" , "wtf!" >>> a is b True # 3.7 版本返回結(jié)果為 False. # example4: >>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa' True >>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa' False # 3.7 版本返回結(jié)果為 True 字符串的這些問題,像是在和你說 1 != 1 一樣坑爹。 究其原因,其實(shí)是CPython在編譯的時(shí)候會自動進(jìn)行優(yōu)化," />
0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python 小坑之字符串駐留

科技綠洲 ? 來源:Python實(shí)用寶典 ? 作者:Python實(shí)用寶典 ? 2023-11-03 11:55 ? 次閱讀

本文整理了許多字符串駐留的坑,部分整合自wtfpython英文版,并增加了大量的后續(xù)說明。

  1. # example1:

  2. >>> a ="wtf"

  3. >>> b ="wtf"

  4. >>> a is b

  5. True

  6. # example2:

  7. >>> a ="wtf!"

  8. >>> b ="wtf!"

  9. >>> a is b

  10. False

  11. # example3:

  12. >>> a, b ="wtf!","wtf!"

  13. >>> a is b

  14. True# 3.7 版本返回結(jié)果為 False.

  1. # example4:

  2. >>>'a'*20is'aaaaaaaaaaaaaaaaaaaa'

  3. True

  4. >>>'a'*21is'aaaaaaaaaaaaaaaaaaaaa'

  5. False# 3.7 版本返回結(jié)果為 True

字符串的這些問題,像是在和你說 1 != 1 一樣坑爹。

究其原因,其實(shí)是CPython在編譯的時(shí)候會自動進(jìn)行優(yōu)化,在某些情況下它會嘗試使用已經(jīng)存在的不可變對象,而不是創(chuàng)建一個(gè)新的對象,而恰好,字符串就是不可變對象。這種使用已存在的不可變對象的行為被稱為“駐留 ” 。

駐留的原本設(shè)計(jì)意圖是用于節(jié)省內(nèi)存的,但是確實(shí)有時(shí)候會坑到程序員。怎樣判斷自己的字符串會否被駐留呢?請看這份代碼:
https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19

簡單地來講:

1.所有長度為0和1的字符串都會被駐留

2.字符串在編譯時(shí)被實(shí)現(xiàn)的會被駐留(如'wtf'會被駐留,但是 ''.join(['w', 't', 'f']) 不會)

3.字符串中只包含ASCII下的字母、數(shù)字和下劃線時(shí)會被駐留. 所以'wtf!'由于包含!不會被駐留。

我們的example1中,由于發(fā)生了駐留,所以a和b是同一個(gè)字符串對象。而example2中,由于沒有發(fā)生字符串駐留,a="wtf!"和b="wtf!"實(shí)際上使用的不是同一個(gè)字符串對象,你可以使用id獲得對象的唯一標(biāo)志,你會發(fā)現(xiàn)它們的不同:

a和b都為wtf!時(shí):

  1. >>> a ="wtf!"

  2. >>> b ="wtf!"

  3. >>> a is b

  4. False

  5. >>> a == b

  6. True

  7. >>> id(a)

  8. 2272774097864

  9. >>> id(b)

  10. 2272774097024

再來看看沒有發(fā)生駐留時(shí)的情況,a和b都為wtf時(shí):

  1. # a和b都為wtf

  2. >>> a ="wtf"

  3. >>> b ="wtf"

  4. >>> a is b

  5. True

  6. >>> a == b

  7. True

  8. >>> id(a)

  9. 2272774096744

  10. >>> id(b)

  11. 2272774096744

明白了吧?如果你想從結(jié)果識別對象是否發(fā)生駐留,關(guān)鍵就看對象的唯一標(biāo)志有沒有被改變。

不過,如example3所示,當(dāng)你在同一行中將a和b都設(shè)置為 wtf! 的時(shí)候,Python解釋器會創(chuàng)建一個(gè)新的對象,然后同時(shí)引用第二個(gè)變量,這時(shí)候它兩的唯一標(biāo)志id就是一樣的。(example3僅適用于python3.7以下,后面被改了)。

example4中,發(fā)生了常量折疊,這其實(shí)也是一種優(yōu)化技術(shù)。編譯時(shí)表達(dá)式 'a'*20 會被替換成 'aaaaaaaaaaaaaaaaaaaa' (不要數(shù)了,20個(gè)),不過只有長度小于20的字符串才會發(fā)生常量替換,這就是為什么 'a'*21并不等于 'aaaaaaaaaaaaaaaaaaaaa' (不要數(shù)了,21個(gè)) 。

好,感謝大家的閱讀,今天的.....等等,你以為這就結(jié)束了嗎?還有呢:

  1. >>> a =10

  2. >>> b =10

  3. >>> a is b

  4. True

  5. >>> a =256

  6. >>> b =256

  7. >>> a is b

  8. True

  9. >>> a =257

  10. >>> b =257

  11. >>> a is b

  12. False

這又是為啥啊?

請注意,Python中,對于整數(shù)對象,如果其值處于[-5,256]的閉區(qū)間內(nèi),則值相同的對象是同一個(gè)對象,否則為不同對象。我知道你想問,別問,問就是源碼本身就這么寫的。

(其實(shí)主要還是從性能方面考慮,-5到256這段數(shù)值被經(jīng)常使用,因此干脆設(shè)為同一個(gè)對象重復(fù)使用,避免分配空間—賦予類別—賦予初始值等一系列操作)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    567

    瀏覽量

    20434
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    647

    瀏覽量

    32741
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4758

    瀏覽量

    84289
  • Examples
    +關(guān)注

    關(guān)注

    0

    文章

    2

    瀏覽量

    1592
收藏 人收藏

    評論

    相關(guān)推薦

    Labview截取字符串

    Labview截取字符串,很好的Labview資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:23 ?0次下載

    Labview連接字符串

    Labview連接字符串,很好的Labview資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:23 ?0次下載

    Labview搜索替換字符串

    Labview搜索替換字符串,很好的Labview資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:23 ?0次下載

    Labview替換子字符串

    Labview替換子字符串,很好的Labview資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:43 ?0次下載

    Labview字符串長度函數(shù)

    Labview字符串長度函數(shù),很好的Labview資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:43 ?0次下載

    python字符串拼接方式了解

    python字符串拼接的方式 在Python的實(shí)際開發(fā)中,很多都需要用到字符串拼接,python字符串
    發(fā)表于 12-06 10:09 ?1012次閱讀

    什么是復(fù)制字符串?Python如何復(fù)制字符串

    連續(xù)幾篇文章都在寫 Python 字符串,這出乎我的意料了。但是,有的問題,不寫不行,特別是那種靈機(jī)一動想到的問題,最后你發(fā)現(xiàn),很多人根本不懂卻又誤以為自己懂了。那就繼續(xù)刨根問底,探究個(gè)明白吧
    發(fā)表于 11-25 10:32 ?2958次閱讀

    2.2 python字符串類型

    2.2 python字符串類型 1. 如何定義字符串? 字符串Python中最常用的數(shù)據(jù)類型之一。 使用單引號或雙引號來創(chuàng)建
    的頭像 發(fā)表于 02-17 17:08 ?1373次閱讀

    Python-字符串

    字符串就是 一字符 ,是編程語言中表示文本的數(shù)據(jù)類型,在Python中使用一對雙引號 "" 或者一對單引號來定義.
    的頭像 發(fā)表于 02-16 15:05 ?1044次閱讀
    <b class='flag-5'>Python</b>-<b class='flag-5'>字符串</b>

    什么是字符串

    Python 中有很多數(shù)據(jù)類型,字符串是其中的一種
    的頭像 發(fā)表于 02-23 14:55 ?5430次閱讀
    什么是<b class='flag-5'>字符串</b>

    python字符串序列操作和不可變性

    初識python字符串序列操作和不可變性。python字符串序列操作為序列通用操作,python字符串
    的頭像 發(fā)表于 02-23 15:01 ?792次閱讀

    python字符串有哪些特定方法

    python字符串序列操作也適用于列表和元組。 python字符串還有獨(dú)有方法,即字符串對象的函數(shù),其他對象不可調(diào)用,只有
    的頭像 發(fā)表于 02-23 15:02 ?631次閱讀

    淺析python字符串模式匹配

    python字符串可以通過re模塊的模式匹配來處理文本。
    的頭像 發(fā)表于 02-23 15:04 ?2270次閱讀

    Python中檢查字符串包含的方法

    Python 有多種處理字符串的方法。今天我們介紹如何檢查一個(gè)字符串中是否包含另一個(gè)字符串。
    的頭像 發(fā)表于 05-14 16:02 ?1.6w次閱讀

    python輸出固定長度的字符串

    Python 是一種強(qiáng)大而靈活的編程語言,具有許多用于處理字符串的功能。在 Python 中,有多種方法可以輸出固定長度的字符串。下面將詳細(xì)介紹這些方法。 方法一:使用
    的頭像 發(fā)表于 11-22 10:41 ?2822次閱讀