Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

ปริศนา A += B ใน Python


ในบทความนี้ เราจะดูว่าเกิดอะไรขึ้นเมื่อเราอัปเดตค่าใน Tuple ซึ่งเป็น immutable จริงๆ เราจะสามารถรวมค่าใหม่กับค่าเก่าได้แต่จะโยนข้อผิดพลาด เราสามารถศึกษา bytecode ของข้อผิดพลาดและเข้าใจได้ดีขึ้นว่ากฎของ Tuple ทำงานอย่างไร

ก่อนอื่นเรากำหนด Tuple แล้วสั่งอัปเดตองค์ประกอบสุดท้ายดังนี้

ตัวอย่างโค้ด

>>> tupl = (5, 7, 9, [1, 4])
>>> tupl[3] += [6, 8]

ผลลัพธ์

การรันโค้ดข้างต้นจะได้ผลลัพธ์ดังนี้ -

Traceback (most recent call last):
  File "", line 1, in
TypeError: 'tuple' object does not support item assignment
>>> tupl
(5, 7, 9, [1, 4, 6, 8])

ตอนนี้เพื่อศึกษา bytecode ของวิธีข้างต้น เราใส่โค้ดลงในฟังก์ชันและใช้เมธอด dis เพื่อแสดง bytecode เราได้ข้อผิดพลาดเดียวกันแต่อย่างละเอียดขึ้น

ตัวอย่างโค้ด

def immut_function():
    tupl = (5, 7, 9, [1, 4])
    tupl[3] += [6, 8]

immut_function()

ผลลัพธ์

การรันโค้ดข้างต้นจะได้ผลลัพธ์ดังนี้ -

TypeError Traceback (most recent call last)
in ()
    2 tupl = (5, 7, 9, [1, 4])
    3 tupl[3] += [6, 8]
----> 4 immut_function()
in immut_function()
    1 def immut_function():
    2 tupl = (5, 7, 9, [1, 4])
----> 3 tupl[3] += [6, 8]
4 immut_function()
TypeError: 'tuple' object does not support item assignment

ต่อไปเราแสดง bytecode ของฟังก์ชันข้างต้นเพื่อดูรายละเอียดของการกำหนดค่า Tuple และข้อผิดพลาด

ตัวอย่างโค้ด

import dis
dis.dis(immut_function)

ผลลัพธ์

การรันโค้ดข้างต้นจะได้ผลลัพธ์ดังนี้ -

2     0 LOAD_CONST               1 (5)
      3 LOAD_CONST               2 (7)
      6 LOAD_CONST               3 (9)
      9 LOAD_CONST               4 (1)
     12 LOAD_CONST               5 (4)
     15 BUILD_LIST               2
     18 BUILD_TUPLE              4
     21 STORE_FAST               0 (tupl)
3    24 LOAD_FAST                0 (tupl)
     27 LOAD_CONST               6 (3)
     30 DUP_TOPX                 2
     33 BINARY_SUBSCR
     34 LOAD_CONST               7 (6)
     37 LOAD_CONST               8 (8)
     40 BUILD_LIST               2
     43 INPLACE_ADD
     44 ROT_THREE
     45 STORE_SUBSCR
     46 LOAD_CONST               0 (None)
     49 RETURN_VALUE

ข้อสรุปคือ ไม่ควรใส่องค์ประกอบ mutable ลงใน Tuple แม้การกำหนดค่าจะเป็นไปได้ แต่จะโยนข้อยกเว้น ตามที่แสดงในขั้นตอนที่มีค่า 46 การกำหนดค่าล้มเหลวเพราะ Tuple เป็น immutable object