90% lập trình viên Python đều mắc lỗi ngớ ngẩn này, còn bạn thì sao ?
Mảng trong Python luôn rất kì diệu. Bạn có thể làm bất kì điều gì với mảng. Đẩy data vào, thay đổi thứ tự, trộn, kết hợp… đôi khi tôi cảm thấy không cần bất kì một quy tắc nào cả, thật là mạnh mẽ!
Nhưng đi kèm với nó là một vài rắc rối tiềm ẩn như đôi khi dữ liệu “không cánh mà bay” dù đã set những thay đổi ở một cách chắc chắn ở phía bên dưới nhưng dữ liệu vẫn liên tục bị thay đổi và bạn phải mất hàng giờ liền để đi tìm nguyên nhân. Bài viết này có thể sẽ giúp bạn tiết kiệm hàng giờ đó, bonus thêm 1 shortcut cực kì nhanh chóng mà rất ít người biết.
Bắt đầu thôi, Naruto – phân thân chi thuật !
Lỗi thường gặp
Đầu tiên tôi sẽ nói về lỗi trường gặp trước nhé
Bạn có 1 list các công việc trong ngày, tới cuối ngày bạn cần xuất ra 2 mục : Tất cả task và các task còn lại
Okay, bắt đầu code thôi, bài này dễ, 3 giây là xong.
Nào, giờ hãy hít thật sâu, dành 3 giây để suy nghĩ xem tại sao nào…
Vẫn không tìm ra ư, cùng tìm hiểu tiếp nhé
Vấn đề là list ở Python giống như một căn hộ chung vậy, khi bạn thực hiện remain_tasks = all_tasks
bạn sẽ không tạo ra một bản sao cho căn hộ của mình, bạn chỉ tạo ra một chìa khóa thứ 2 đến cùng 1 căn hộ ban đầu. Khi bạn thay đổi đồ đạc trong căn hộ thì mọi người cũng bị thay đổi theo bằng chìa khóa bất kì.
Hậu quả
Mất bản sao lưu : Hãy tưởng tượng lưu lượng công việc của bạn là sao lưu dữ liệu, nhưng thật tệ khi bản sao lưu lại không phải là bản sao lưu, nó chính là bản gốc.
Ảnh hưởng dữ liệu gốc : Các hàm được cho là xử lí dữ liệu sao lưu lại vô tình thay đổi dữ liệu gốc giống như việc thay đổi nội thất trong căn nhà mà tôi nói đến ở phía trên vậy
Khó để điều tra lỗi : Điều tồi tệ nhất là quá trình này xảy ra “ngầm” và rất lâu sau bạn có thể mới phát hiện ra nó, và sau đó mất hàng giờ để tìm hiểu xem lỗi ở phần nào, tại sao lại lỗi, rất khó để tracking bug này nếu bạn chưa từng mắc phải.
Giải pháp
Hãy tưởng tượng danh sách như các thư mục. Đôi khi, bạn cần một thư mục mới với các nhãn giống như thư mục cũ (đó là một bản sao nông – Shallow Copy). Còn đôi khi, bạn cần một thư mục hoàn toàn mới với các bản sao hoàn toàn của tất cả các tập tin bên trong (đó là một bản sao sâu – Deep Copy).
Tóm lại đi phỏng vấn thì phải trả lời thế nào cho ngắn gọn và mượt :
Shallow Copies : Hoạt động tốt với list có các phần tử không có các list lồng nhau hoặc các đối tượng bên trong.
Deep Copies : Hoạt động tốt với list có các phần tử có các list lồng nhau hoặc các đối tượng bên trong.
Vậy thế nào là list có các phần tử lồng nhau ? Đây, ví dụ đây :
“Vẫn chưa rõ ràng lắm nhỉ Hoàng Anh ơi, bạn có thể cho tôi ví dụ được không?”
Tất nhiên rồi, ví dụ với Shallow Copies nhé :
Bạn có thể thấy hàm copy()
hoạt động tốt với mảng không lồng nhau và đơn giản như [1.2.3.4]
còn với mảng có các phần tử lồng nhau như [["Alice", "Bob"], ["Charlie"]]
thì khi thay đổi 1 phần tử trong array con của array lớn thì nó vẫn thay đổi vào array gốc.
Với trường hợp thứ 2 thì đơn giản hãy sử dụng Deep Copies copy.deepcopy()
như sau :
Nhớ import copy
nhé
Bạn đã hiểu rồi đấy.
Còn chi tiết về sự khác nhau giữa 2 kiểu copy này thì có thể tôi sẽ viết 1 bài viết khác để nói về điều đó sau, còn giờ thì cứ thực chiến cái đã.
Bonus :
Như đã hứa ở phần đầy, đây là shortcut cho hàm copy bằng array[:]
thay vì array.copy()