Pythonメタグループの可変属性特例について

3573 ワード

メタグループは可変リストと見なすことができ,すなわちメタグループの中の要素は勝手に変えることができない.ただし、メタグループは、要素としてリストを受け入れる可変オブジェクトです.これにより、予想外の境界効果が発生します.『流暢なPython』第2.6章より抜粋.
1パズル
要素のタプルとしてリストを使用する可変オブジェクトを定義し、スライスを使用してリストオブジェクトを操作します.
>>> t = (1, 2 ,[ 30, 40])
>>> t[2] += [50, 60]

いったい次の4つの状況が発生するのはどれですか?
A.tは(1,2,[30,40,50,60])になる.
B.tupleはその要素の付与をサポートしていないため、TypeError異常が放出されます.
C.以上はどちらも違います.
D.AもBも正しい.
2正解
D.t[2]は変更されたが、異常放出もあった.
>>> t[2] += [50, 60]
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40, 50, 60])

3迷いを解く
以下、Pythonが式t[2]+=[50,60]で生成したバイトコードを見てみると、この現象の背後にある原因が明らかになる可能性がある.
>>> import dis
>>> dis.dis('t[2] += [50, 60]')
  1           0 LOAD_NAME                0 (t)
              2 LOAD_CONST               0 (2)
              4 DUP_TOP_TWO
              6 BINARY_SUBSCR                       ①
              8 LOAD_CONST               1 (50)
             10 LOAD_CONST               2 (60)
             12 BUILD_LIST               2
             14 INPLACE_ADD                         ②
             16 ROT_THREE
             18 STORE_SUBSCR                        ③
             20 LOAD_CONST               3 (None)
             22 RETURN_VALUE

①t[2]の値をTOS(TopOf Stack,スタックの先端)に格納する.
②TOS+=bを計算します.このステップは、TOSが可変オブジェクト(すなわち、インスタンス内のリスト)を指すため、完了することができる.
③t[2]=TOS付与.このステップが失敗したのは,tが可変メタグループであるためである.
4教訓
  • 可変オブジェクトをメタグループに入れないでください.
  • 増分賦値は原子操作ではない.私たちもさっき見ましたが、異常を投げましたが、操作は完了しました.
  • はPythonのバイトコードを生産するのは難しくなく、コードの背後にある動作メカニズムを理解するのに役立ちます.

  • 5選択問題
    *t[2].extend([50, 60])と書けば避けることができますが、なぜですか?*