<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      一個關于 += 的謎題

      原文鏈接: 一個關于 += 的謎題

      今天在看書過程中發現了一個問題,還挺有意思的,分享給大家。

      下面兩個 Python 表達式會產生什么結果?

      t = (1, 2, [3, 4])
      t[2] += [5, 6]
      

      給四個備選答案:

      1. t 變成 (1, 2, [3, 4, 5, 6])
      2. 因為 tuple 不支持對它的元素賦值,所以會拋出 TypeError 異常。
      3. 以上兩個都不是。
      4. 以上兩個都是對的。

      當時看到這個問題,第一反應就是選 2。因為 tuple 是不可變對象,不支持對它的元素賦值,會報錯。

      但事實上,這道題的正解是 4。

      在終端里驗證一下:

      Python 3.8.2 (default, Oct  2 2020, 10:45:42)
      [Clang 12.0.0 (clang-1200.0.32.27)] on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>>
      >>> t = (1, 2, [3, 4])
      >>> t[2] += [5, 6]
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: 'tuple' object does not support item assignment
      

      結果是沒問題的,t 被修改了,但是也報錯了。

      還可以在 Python Tutor 上分析一下:

      網站地址: https://pythontutor.com/

      這個網站可以可視化分析 Python 的運行過程和原理。

      執行第一個表達式:

      執行第二個表達式:

      為什么會這樣呢?可以從兩個方面來解釋:

      一、對象類型

      Python 中的對象可以分成兩類,可變對象和不可變對象,比如一些內置類型:

      1. 可變對象:list,set,dict。
      2. 不可變對象:int,float,bool,string,tuple。

      舉一個例子:

      可變對象:

      >>> a = [1, 2, 3]
      >>> id(a)
      2139167246856
      >>> b = a
      >>> id(b)
      2139167246856
      >>> a[1] = 4
      >>> a
      [1, 4, 3]
      >>> b
      [1, 4, 3]
      >>> id(a)
      2139167246856
      >>> id(b)
      2139167246856
      

      可以看到,改變 a 的同時 b 也跟著變,因為他們始終指向同一個地址。

      不可變對象:

      >>> a = (1, 2, 3)
      >>> id(a)
      2139167074776
      >>> b = a
      >>> a = (4, 5, 6)
      >>> a
      (4, 5, 6)
      >>> b
      (1, 2, 3)
      >>> id(a)
      2139167075928
      >>> id(b)
      2139167074776
      

      可以看到,a 的值改變后,它的地址也發生了變化,而 b 還是原來的地址,并且原地址中的內容也沒有發生變化。

      二、字節碼

      首先解釋一下字節碼是什么?

      Python 執行程序時會把源碼文件編譯成字節碼文件,存放在 __pycahe 目錄內,文件用 .pyc 結尾。之后如果不再修改源碼文件,運行時則直接使用 .pyc 文件編譯成機器碼,這樣不但運行速度快,而且支持多個操作系統。

      字節碼,其實就是一種中間代碼。

      下面用 dis 模塊來看一下表達式 s[a] += b 的執行過程:

      >>> import dis
      >>> dis.dis('s[a] += b')
        1           0 LOAD_NAME                0 (s)
                    2 LOAD_NAME                1 (a)
                    4 DUP_TOP_TWO
                    6 BINARY_SUBSCR
                    8 LOAD_NAME                2 (b)
                   10 INPLACE_ADD
                   12 ROT_THREE
                   14 STORE_SUBSCR
                   16 LOAD_CONST               0 (None)
                   18 RETURN_VALUE
      >>>
      

      通過分析字節碼,可以看到其中的關鍵三步:

      1. 4 DUP_TOP_TWO:將 s[a] 存入 TOS(Top Of Stack)。
      2. 10 INPLACE_ADD:執行 TOS += b,帶入到文章開頭的表達式,就相當于向 t[2] 中添加元素,因為 t[2] 是 list,可變對象,所以這一操作沒有問題。
      3. 14 STORE_SUBSCR:將結果保存回 s[a] = TOS,這相當于將結果重新賦值回 t,由于 t 是 tuple,不可變對象,所以報錯。

      雖然這個問題在平時開發中可能并不常見,但通過分析還是有不少知識點可以深挖的。

      簡單總結以下三點:

      1. 不要把可變對象放在元組里面。
      2. 增量賦值不是一個原子操作。我們剛才也看到了,它雖然拋出了異常,但還是完成了操作。
      3. 查看 Python 的字節碼并不難,而且它對我們了解代碼背后的運行機制很有幫助。

      以上就是本文的全部內容,如果覺得還不錯的話,歡迎點贊轉發,多謝


      推薦閱讀:

      • 計算機經典書籍(含下載方式)
      • 技術博客 硬核后端開發技術干貨,內容包括 Python、Django、Docker、Go、Redis、ElasticSearch、Kafka、Linux 等。
      • Go 程序員 Go 學習路線圖,包括基礎專欄,進階專欄,源碼閱讀,實戰開發,面試刷題,必讀書單等一系列資源。
      • 面試題匯總 包括 Python、Go、Redis、MySQL、Kafka、數據結構、算法、編程、網絡等各種常考題。
      posted @ 2022-02-28 12:28  yongxinz  閱讀(447)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品日本久久一区二区三区| 无码伊人66久久大杳蕉网站谷歌| 日本丰满熟妇videossex一| 乱码精品一区二区亚洲区| 国产97视频人人做人人爱| 国产亚洲一本大道中文在线| 极品蜜臀黄色在线观看| 香蕉亚洲欧洲在线一区| 亚洲欧美v国产一区二区| 久99久热免费视频播放| 卢氏县| 九九热在线观看视频精品| 亚洲熟妇精品一区二区| 国产精品高清中文字幕| 国产免费一区二区三区在线观看| 国产成人无码免费看视频软件| 天堂а√在线最新版中文在线| 欧美激情 亚洲 在线| 国内精品大秀视频日韩精品| 亚洲日本乱码在线观看| 在线播放国产精品三级网| 亚洲欧洲精品一区二区| 免费大片黄国产在线观看| 国产黄色精品一区二区三区| 国产成人精品无码专区| 999精品全免费观看视频| 观塘区| 日韩精品中文字幕有码| 国内精品伊人久久久久av| 九九在线精品国产| 久久精品国产99精品亚洲| 国产精品人妻系列21p| 国产精品伊人久久综合网| 亚洲成人av免费一区| 四虎永久精品免费视频| 国内精品久久久久影视| 果冻传媒董小宛视频| 欧洲亚洲成av人片天堂网| 熟女丰满老熟女熟妇| a在线观看视频在线播放| 国产片AV国语在线观看手机版|