เปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้ใน Python

เปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้ใน Python

บทความนี้อธิบายเกี่ยวกับการเปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้ใน Python

YouTube Video

เปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้ใน Python

"เปลี่ยนแปลงได้" และ "เปลี่ยนแปลงไม่ได้" หมายถึง ความสามารถในการเปลี่ยนแปลงของวัตถุ (object) การเข้าใจเรื่องนี้ช่วยในการ หลีกเลี่ยงข้อผิดพลาดที่ไม่คาดคิด และ การจัดการหน่วยความจำอย่างมีประสิทธิภาพ

อะไรคือเปลี่ยนแปลงได้?

เปลี่ยนแปลงได้ หมายถึงวัตถุที่สามารถ เปลี่ยนแปลงสถานะภายในหลังจากที่สร้างขึ้นแล้ว

ประเภทข้อมูลเปลี่ยนแปลงได้หลัก

  • list
  • dict
  • set
  • คลาสที่ผู้ใช้กำหนดเอง (หาก attribute ของมันสามารถถูกแก้ไขได้)

ตัวอย่าง: การแก้ไข List

1numbers = [1, 2, 3]
2numbers[0] = 100
3print(numbers)  # [100, 2, 3]

List เป็นวัตถุเปลี่ยนแปลงได้ และเราสามารถปรับเปลี่ยนองค์ประกอบภายในได้ตามต้องการ

อะไรคือเปลี่ยนแปลงไม่ได้?

เปลี่ยนแปลงไม่ได้ หมายถึงวัตถุที่ ไม่สามารถเปลี่ยนแปลงได้หลังจากที่ถูกสร้างขึ้นแล้ว การพยายามแก้ไขวัตถุดังกล่าวจะทำให้เกิดการสร้างวัตถุใหม่ขึ้นแทน

ประเภทข้อมูลเปลี่ยนแปลงไม่ได้หลัก

  • int
  • float
  • str
  • tuple
  • bool
  • frozenset

ตัวอย่าง: การแก้ไข String

1text = "hello"
2# text[0] = "H"  # TypeError: 'str' object does not support item assignment
3
4text = "H" + text[1:]  # Creates a new string
5print(text)  # "Hello"

String เป็นวัตถุเปลี่ยนแปลงไม่ได้ ดังนั้นคุณไม่สามารถแก้ไขบางส่วนของมันได้

การเปรียบเทียบระหว่างเปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้

 1# Mutable example
 2a = [1, 2, 3]
 3b = a
 4b[0] = 100
 5print(a)  # [100, 2, 3] -> a is also changed
 6
 7# Immutable example
 8x = 10
 9y = x
10y = 20
11print(x)  # 10 -> x is unchanged

ดังที่แสดงในตัวอย่างข้างต้น วัตถุเปลี่ยนแปลงได้ถูกแชร์โดยการอ้างอิง (reference) ดังนั้น มันสามารถส่งผลกระทบต่อตัวแปรอื่นได้ ในทางกลับกัน วัตถุที่ไม่สามารถเปลี่ยนแปลงได้จะสร้างอินสแตนซ์ใหม่เมื่อมีการกำหนดค่าใหม่ โดยค่าต้นฉบับจะไม่ได้รับผลกระทบ

การตรวจสอบพฤติกรรมภายในโดยใช้ id()

ใน Python คุณสามารถใช้ฟังก์ชัน id() เพื่อตรวจสอบ ID ของวัตถุ ID ของวัตถุคล้ายกับที่อยู่ในหน่วยความจำ

 1# Immutable int behavior
 2a = 10
 3print(id(a))  # e.g., 140715920176592
 4a += 1
 5print(id(a))  # e.g., 140715920176624 -> ID has changed
 6
 7# Mutable list behavior
 8b = [1, 2, 3]
 9print(id(b))  # e.g., 2819127951552
10b.append(4)
11print(id(b))  # Same ID -> only the content has changed

ตามที่แสดง วัตถุใหม่จะถูกสร้างขึ้นสำหรับประเภทที่ไม่เปลี่ยนแปลงได้, ในขณะที่ ประเภทที่เปลี่ยนแปลงได้จะถูกแก้ไขในตำแหน่งเดิม

ฟังก์ชันและข้อควรระวังกับวัตถุที่เปลี่ยนแปลงได้และไม่ได้

เมื่อส่งวัตถุที่เปลี่ยนแปลงได้ไปยังฟังก์ชัน ข้อมูลต้นฉบับอาจถูกเปลี่ยนแปลงได้

ตัวอย่าง: ฟังก์ชันที่แก้ไขรายการ

1def modify_list(lst):
2    lst.append(100)
3
4my_list = [1, 2, 3]
5modify_list(my_list)
6print(my_list)  # [1, 2, 3, 100]

ตัวอย่าง: ฟังก์ชันที่แก้ไขตัวเลข

ในทางกลับกัน การพยายามแก้ไขวัตถุที่ไม่สามารถเปลี่ยนแปลงได้จะส่งผลให้มีการสร้างวัตถุใหม่

1def modify_number(n):
2    n += 10
3
4my_number = 5
5modify_number(my_number)
6print(my_number)  # 5 -> unchanged

ข้อควรพิจารณาในการใช้งานจริง

หลีกเลี่ยงการใช้วัตถุที่เปลี่ยนแปลงได้เป็นค่าเริ่มต้นของอาร์กิวเมนต์

 1# Bad example
 2def add_item(item, container=[]):
 3    container.append(item)
 4    return container
 5
 6print(add_item(1))  # [1]
 7print(add_item(2))  # [1, 2] -> unintended behavior
 8
 9# Good example
10def add_item(item, container=None):
11    if container is None:
12        container = []
13    container.append(item)
14    return container

เนื่องจากค่าเริ่มต้นของอาร์กิวเมนต์จะถูกประเมินเพียงครั้งเดียวเมื่อประกาศฟังก์ชัน การใช้วัตถุที่เปลี่ยนแปลงได้อาจนำไปสู่ผลกระทบที่ไม่คาดคิด

สรุป

เพื่อความเข้าใจที่ลึกซึ้งเกี่ยวกับตัวแปรและประเภทข้อมูลใน Python การเข้าใจความแตกต่างระหว่างวัตถุที่เปลี่ยนแปลงได้และไม่ได้เป็นสิ่งสำคัญ การเข้าใจลักษณะเหล่านี้ช่วยให้คุณหลีกเลี่ยงพฤติกรรมที่ไม่ตั้งใจในโค้ดของคุณ และเขียนโปรแกรมที่มีความทนทานและอ่านง่ายขึ้น

คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย

YouTube Video