Có thể thay đổi và Không thể thay đổi trong Python
Bài viết này giải thích về có thể thay đổi và không thể thay đổi trong Python.
YouTube Video
Có thể thay đổi và Không thể thay đổi trong Python
"Có thể thay đổi" và "không thể thay đổi" đề cập đến tính thay đổi của đối tượng. Hiểu được điều này giúp tránh các lỗi không mong muốn và quản lý bộ nhớ hiệu quả.
Có thể thay đổi là gì?
Đối tượng có thể thay đổi có thể thay đổi trạng thái bên trong sau khi được tạo.
Các kiểu dữ liệu chính có thể thay đổi
list
dict
set
- Các lớp do người dùng định nghĩa (nếu các thuộc tính của chúng có thể được thay đổi)
Ví dụ: Thay đổi danh sách
1numbers = [1, 2, 3]
2numbers[0] = 100
3print(numbers) # [100, 2, 3]
Danh sách là một đối tượng có thể thay đổi và các phần tử của nó có thể được thay đổi tự do.
Không thể thay đổi là gì?
Đối tượng không thể thay đổi không thể thay đổi sau khi được tạo. Cố gắng thay đổi chúng sẽ tạo ra một đối tượng mới.
Các kiểu dữ liệu chính không thể thay đổi
int
float
str
tuple
bool
frozenset
Ví dụ: Thay đổi chuỗi
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"
Chuỗi là không thể thay đổi, vì vậy bạn không thể thay đổi một phần của chúng.
So sánh giữa Có thể thay đổi và Không thể thay đổi
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
Như bạn có thể thấy từ ví dụ này, các đối tượng có thể thay đổi được chia sẻ bằng tham chiếu, vì vậy chúng có thể ảnh hưởng đến các biến khác. Mặt khác, các đối tượng bất biến tạo ra các phiên bản mới khi được gán lại, giữ nguyên giá trị gốc không bị ảnh hưởng.
Kiểm tra hành vi bên trong bằng cách sử dụng id()
Trong Python, bạn có thể sử dụng hàm id()
để kiểm tra ID của một đối tượng. ID của đối tượng tương tự như một địa chỉ bộ nhớ.
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
Như được mô tả, một đối tượng mới được tạo cho các kiểu bất biến, trong khi các kiểu có thể thay đổi được chỉnh sửa tại chỗ.
Hàm và sự cẩn trọng với các đối tượng có thể thay đổi và bất biến
Khi truyền một đối tượng có thể thay đổi vào một hàm, dữ liệu gốc có thể bị chỉnh sửa.
Ví dụ: Một hàm sửa đổi một danh sách
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]
Ví dụ: Một hàm sửa đổi một số
Mặt khác, việc cố gắng sửa đổi một đối tượng bất biến dẫn đến việc tạo ra một đối tượng mới.
1def modify_number(n):
2 n += 10
3
4my_number = 5
5modify_number(my_number)
6print(my_number) # 5 -> unchanged
Những lưu ý thực tế
Tránh sử dụng các đối tượng có thể thay đổi làm tham số mặc định
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
15
16print(add_item(1)) # [1]
17print(add_item(2)) # [2]
Vì các tham số mặc định chỉ được đánh giá một lần khi định nghĩa hàm, việc sử dụng các đối tượng có thể thay đổi có thể dẫn đến các tác dụng phụ không mong muốn.
- Trong ví dụ đầu tiên, cùng một đối tượng danh sách được sử dụng mỗi khi gọi
add_item
. Khi gọiadd_item(2)
lần thứ hai, phần tử1
đã thêm trước đó vẫn còn trong danh sách, dẫn đến kết quả là[1, 2]
. - Trong ví dụ cải tiến,
None
được sử dụng làm giá trị mặc định, và một danh sách mới sẽ được tạo ra bên trong hàm nếu đối số làNone
. Điều này đảm bảo rằng mỗi lần gọi hàm sẽ tạo ra một danh sách mới, do đó kết quả trước đó sẽ không ảnh hưởng đến các lần gọi sau.
Tránh sử dụng các đối tượng có thể thay đổi như danh sách hoặc từ điển làm đối số mặc định; thay vào đó, hãy sử dụng None
và khởi tạo chúng bên trong hàm. Đây là một nguyên tắc cơ bản và quan trọng trong Python.
Tóm tắt
Để hiểu sâu về biến và kiểu dữ liệu trong Python, điều quan trọng là phải nắm được sự khác biệt giữa đối tượng có thể thay đổi và bất biến. Hiểu rõ những đặc điểm này sẽ giúp bạn tránh những hành vi không mong muốn trong mã của mình và viết những chương trình vững chắc và dễ đọc hơn.
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.