Bài viết này trình bày hai chủ đề chính: cách sao chép danh sách trong Python, phân biệt giữa shallow copy và deep copy, và cách sử dụng vòng lặp while cho việc kiểm soát luồng chương trình.
I. Sao chép Danh sách trong Python
Khi làm việc với danh sách (list) trong Python, có hai phương pháp sao chép chính:
1. Shallow Copy (Sao chép nông)
Shallow copy tạo ra một đối tượng danh sách mới. Tuy nhiên, nó chỉ sao chép các tham chiếu đến các đối tượng bên trong danh sách gốc. Điều này có nghĩa là nếu danh sách gốc chứa các đối tượng có thể thay đổi (như danh sách con), cả danh sách gốc và bản sao sẽ cùng trỏ đến các đối tượng đó.
Phương pháp thực hiện Shallow Copy:
original_list = ['egon', 'lxx', [1, 2]]
shallow_copied_list = original_list.copy()
# Hoặc sử dụng slicing: shallow_copied_list = original_list[:]
Khi một đối tượng có thể thay đổi bên trong original_list được sửa đổi, shallow_copied_list cũng sẽ bị ảnh hưởng và ngược lại.
2. Deep Copy (Sao chép sâu)
Deep copy tạo ra một đối tượng danh sách mới hoàn toàn độc lập với danh sách gốc. Nó không chỉ sao chép danh sách mà còn sao chép đệ quy tất cả các đối tượng bên trong danh sách đó. Do đó, mọi thay đổi đối với danh sách gốc hoặc bản sao sẽ không ảnh hưởng đến đối tượng kia.
Phương pháp thực hiện Deep Copy:
import copy
original_list = ['egon', 'lxx', [1, 2]]
deep_copied_list = copy.deepcopy(original_list)
Sự khác biệt cốt lõi nằm ở chỗ: shallow copy chia sẻ tham chiếu đến các đối tượng có thể thay đổi, trong khi deep copy tạo ra các bản sao độc lập cho tất cả các đối tượng.
II. Kiểm soát Luồng với Vòng lặp while
Vòng lặp while cho phép thực thi một khối mã lặp đi lặp lại miễn là một điều kiện nhất định còn đúng.
1. Cú pháp và Sử dụng Cơ bản
Cú pháp của vòng lặp while như sau:
while dieu_kien:
# Khối mã thực thi khi dieu_kien là True
# Có thể có nhiều dòng lệnh
pass # Placeholder
# Mã thực thi sau khi vòng lặp kết thúc
print("Hoàn thành vòng lặp.")
Ví dụ:
counter = 0
while counter < 5:
print(counter)
counter += 1 # Cập nhật điều kiện để tránh vòng lặp vô hạn
print('Đã thoát vòng lặp.')
2. Vòng lặp Vô hạn và Hiệu suất
Một vòng lặp while có thể trở thành vòng lặp vô hạn (infinite loop) nếu điều kiện của nó không bao giờ trở thành False. Điều này thường xảy ra khi biến điều kiện không được cập nhật bên trong vòng lặp.
Ví dụ về vòng lặp vô hạn (cần cẩn thận khi chạy):
# Vòng lặp vô hạn tiềm ẩn nếu counter không tăng
# while counter < 5:
# print(counter)
# Vòng lặp vô hạn rõ ràng
# while True:
# name = input('Nhập tên của bạn: ')
# print(name)
Các vòng lặp vô hạn chỉ thực hiện tính toán đơn thuần (ví dụ: 1+1 trong một vòng lặp while True mà không có lệnh print hoặc I/O) có thể gây ra vấn đề nghiêm trọng về hiệu suất vì chúng chiếm toàn bộ tài nguyên CPU mà không tạo ra kết quả hữu hình.
3. Ứng dụng của Vòng lặp while
Vòng lặp while rất hữu ích khi bạn cần thực hiện một hành động lặp lại cho đến khi một điều kiện cụ thể được thỏa mãn, ví dụ như trong các tình huống xác thực người dùng.
Ví dụ: Xác thực người dùng
Giả sử bạn muốn cho phép người dùng nhập tài khoản và mật khẩu, và nếu nhập sai, họ có thể thử lại.
# Mã không có vòng lặp while (cần lặp lại thủ công)
# username = 'abc'
# pwd = '123'
# inp_name = input('Nhập tài khoản: ')
# inp_pwd = input('Nhập mật khẩu: ')
# if username == inp_name and pwd == inp_pwd:
# print('Chào mừng!')
# else:
# print('Sai thông tin.')
# # Nếu muốn thử lại, bạn phải sao chép và dán khối mã này.
# Sử dụng vòng lặp while để cho phép thử lại
username = 'abc'
pwd = '123'
while True: # Vòng lặp vô hạn cho đến khi có lệnh break
inp_name = input('Nhập tài khoản: ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
break # Thoát vòng lặp khi đăng nhập thành công
else:
print('Sai thông tin. Vui lòng thử lại.')
4. Hai Cách Thoát khỏi Vòng lặp
4.1. Thay đổi Điều kiện thành False
Bạn có thể đặt một biến cờ (flag) và thay đổi giá trị của nó thành False để kết thúc vòng lặp. Tuy nhiên, sự thay đổi này chỉ có hiệu lực vào lần kiểm tra điều kiện tiếp theo.
username = 'abc'
pwd = '123'
login_success = False # Biến cờ
while not login_success:
inp_name = input('Nhập tài khoản: ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
login_success = True # Thay đổi cờ, vòng lặp sẽ kết thúc ở lần kiểm tra sau
else:
print('Sai thông tin. Vui lòng thử lại.')
# Lưu ý: Ngay cả khi login_success = True, các lệnh sau đó trong lần lặp hiện tại vẫn sẽ chạy.
4.2. Sử dụng Lệnh break
Lệnh break ngay lập tức chấm dứt vòng lặp hiện tại, bất kể điều kiện của vòng lặp. Mã sau break trong cùng một khối lệnh sẽ không được thực thi.
username = 'abc'
pwd = '123'
while True:
inp_name = input('Nhập tài khoản: ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
break # Thoát ngay lập tức khỏi vòng lặp while
else:
print('Sai thông tin. Vui lòng thử lại.')
print('==== Đã thoát chương trình ====') # Dòng này chỉ in ra nếu vòng lặp kết thúc bằng break
Nếu điều kiện đăng nhập đúng, break sẽ được thực thi và thông báo "==== Đã thoát chương trình ====" sẽ được in ra. Nếu điều kiện sai, vòng lặp tiếp tục và dòng cuối cùng không được in.
5. Lồng Vòng lặp while
5.1. Sử dụng Biến Cờ (Tag)
Khi lồng vòng lặp, bạn có thể sử dụng biến cờ để kiểm soát việc thoát khỏi các vòng lặp lồng nhau.
username = 'abc'
pwd = '123'
tag = True # Biến cờ chính
while tag:
inp_name = input('Nhập tài khoản: ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
# Vòng lặp lồng nhau
while tag:
cmd = input('Nhập lệnh (hoặc "q" để thoát): ')
if cmd == 'q':
tag = False # Đặt cờ thành False để thoát cả hai vòng lặp
else:
print(f'Đang tải lệnh: {cmd}')
else:
print('Sai thông tin. Vui lòng thử lại.')
# Nếu không đăng nhập thành công, vòng lặp ngoài sẽ tiếp tục.
print('==== Đã thoát chương trình ====')
5.2. Sử dụng break trong Vòng lặp Lồng nhau
Mỗi lệnh break chỉ thoát khỏi vòng lặp gần nhất mà nó thuộc về. Để thoát khỏi nhiều vòng lặp, bạn cần sử dụng break tương ứng cho mỗi vòng lặp.
username = 'abc'
pwd = '123'
while True: # Vòng lặp ngoài
inp_name = input('Nhập tài khoản: ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
while True: # Vòng lặp trong
cmd = input('Nhập lệnh (hoặc "q" để thoát): ')
if cmd == 'q':
break # Thoát vòng lặp trong
else:
print(f'Đang tải lệnh: {cmd}')
# Sau khi vòng lặp trong kết thúc (do break), vòng lặp ngoài sẽ tiếp tục
# Nếu muốn thoát cả hai, cần thêm break ở đây hoặc sử dụng biến cờ.
# Để thoát hoàn toàn, ta có thể thêm break thứ hai ở đây.
break # Thoát vòng lặp ngoài
else:
print('Sai thông tin. Vui lòng thử lại.')
print('==== Đã thoát chương trình ====')
6. Sử dụng continue với while
Lệnh continue bỏ qua phần còn lại của khối mã trong lần lặp hiện tại và chuyển sang lần lặp tiếp theo. Mã nằm sau continue trong cùng một khối lệnh sẽ không bao giờ được thực thi.
counter = 0
while counter < 6:
if counter == 4:
print("Bỏ qua số 4")
counter += 1 # Phải cập nhật biến điều kiện trước continue
continue # Chuyển sang lần lặp tiếp theo, bỏ qua print(counter)
print(counter)
counter += 1
print("Hoàn thành.")
Kết quả sẽ in ra 0, 1, 2, 3, và sau đó là thông báo "Bỏ qua số 4" và 5.
7. while với else (Kết hợp với break)
Khối else đi kèm với vòng lặp while sẽ chỉ được thực thi khi vòng lặp kết thúc một cách tự nhiên (tức là điều kiện vòng lặp trở thành False), mà không bị chấm dứt bởi lệnh break.
Ví dụ ứng dụng: Giới hạn số lần thử đăng nhập
username = 'abc'
pwd = '123'
login_attempts = 0
max_attempts = 3
success = False
while login_attempts < max_attempts:
inp_name = input(f'Nhập tài khoản (Thử {login_attempts + 1}/{max_attempts}): ')
inp_pwd = input('Nhập mật khẩu: ')
if username == inp_name and pwd == inp_pwd:
print('Chào mừng!')
success = True
break # Thoát vòng lặp nếu đăng nhập thành công
else:
print('Sai thông tin.')
login_attempts += 1
# Khối else này sẽ chỉ chạy nếu vòng lặp kết thúc mà không gặp break
# Trong trường hợp này, nó sẽ chạy nếu số lần thử đạt max_attempts và vẫn sai.
if not success:
print('Bạn đã hết số lần thử.')
# Một ví dụ khác về else với break và continue
# counter = 0
# while counter < 6:
# if counter == 4:
# print('Gặp số 4, thoát vòng lặp.')
# break # Nếu gặp 4 thì thoát, else sẽ không chạy
# print(counter)
# counter += 1
# else:
# # Khối này chỉ chạy nếu vòng lặp kết thúc tự nhiên (counter >= 6)
# print('Vòng lặp đã hoàn thành mà không bị break.')