Python: Đây là tính năng chứ không phải bug

Tram Ho

image.png

Ảnh từ hackermoon.com

Python làm một ngôn ngữ khá dễ tiếp cận cho người mới tuy nhiên thì với Python thì cũng có khá nhiều thứ khá nhì nhằng và bài viết này sẽ giúp các bạn hiểu thêm về mấy cái nhì nhằng này. Dưới đây là một số tính năng khá vi diệu có trong Python (Lưu ý đây là tính năng chứ không phải bug).

1. Cấu trúc for-else.

Nhiều ngôn ngữ lập trình có cấu trúc if-else để xử lý các câu lệnh điều kiện. Tuy nhiên, trong Python, bạn thậm chí có thể sử dụng câu lệnh else mà không cần if.

Ví dụ, đoạn mã trên không có câu lệnh if. Nhưng khối mã bên dưới câu lệnh else đã được thực thi thành công!

Đây là cú pháp for-else trong Python.

Đó là một tính năng kỳ lạ và chúng ta nên cẩn thận khi sử dụng nó. Nhưng ý tưởng của nó lại đơn giản đến không ngờ:

Khối else sẽ được thực thi khi vòng lặp for chạy mà không gặp break.

Để chứng minh điều này, hãy xem xét đoạn code sau:

Khi chạy đoạn code trên, danh sách animals chứa “Chicken” vì vậy, vòng lặp for đã bị break và câu lệnh else không được thực thi.

2. Thay đổi Tuples trong Python ?

Như đã biết thì tuples là immutable Python objects (tức là đối tượng không thể thay đổi được). Tuy nhiên thì có một mẹo có thể tạm coi là thay đổi tuples mặc dù thực tế thì bản chất tuples không hề thay đổi.

Nhưng theo cách dưới đây thì ta có thể tạm coi là tuples được thay đổi.

giải thích cho điều này thì tp là một immutable Python objects (bất biến). Tuy nhiên, phần tử đầu tiên trong tp là một list có thể thay đổi được. Khi này, phần tử đầu tiên của tp sẽ trỏ vào địa chỉ ô nhớ lưu trữ list mà có giá trị là [1, 2, 3] ban đầu. Khi ta thay đổi giá trị của phần tử đầu tiên thì tp không đổi tuy nhiên thì ta vẫn có thể coi là tp thay đổi (thay đổi về mặt giá trị trả ra). Các bạn có thể xem xét ví dụ dưới đây để thấy rõ hơn:

3. 256 là 256, nhưng đôi khi 257 không phải 257

Ngạc nhiên chưa, đây là một tính năng ảo diệu của python chứ hoàn toàn không phải lỗi. Khi chạy ví dụ dưới đây với python shell thì kết quả trả ra sẽ khiến bạn bất ngờ.

Về cơ bản, Python tải trước tất cả các số nguyên nhỏ trong phạm vi [-5, 256] để tiết kiệm thời gian và chi phí bộ nhớ. Do đó, khi một số nguyên trong phạm vi này được khai báo, Python chỉ tham chiếu số nguyên được lưu trong bộ nhớ cache và sẽ không tạo bất kỳ đối tượng mới nào. Với mỗi dòng code là một câu lệnh hoàn toàn khác, được phân tích cú pháp và biên dịch riêng, do đó xảy ra trường hợp như trên.

Trong một từ, ab là cùng một đối tượng, nhưng xy là hai đối tượng khác nhau.

Cơ chế này trong Python được gọi là integer interning hoặc integer caching.
Đấy là khi chúng ta viết code trong python shell thì sẽ xảy ra trường hợp này còn khi chúng ta viết chúng trong cùng 1 file, cùng một ngữ cảnh (context), trình biên dịch (complier) thì sẽ không xảy ra trường hợp này.

4. String interning

String interning làm cho các hoạt động xử lý chuỗi phổ biến tiết kiệm thời gian và không gian bằng cách lưu chúng vào bộ nhớ đệm. Thay vì mỗi lần tạo một bản sao mới của chuỗi, phương pháp tối ưu hóa này yêu cầu chỉ giữ một bản sao của chuỗi cho mọi giá trị riêng biệt bất biến thích hợp và sử dụng tham chiếu con trỏ ở bất kỳ đâu được gọi.

Toán tửis trong Python được sử dụng để kiểm tra xem hai đối tượng có tham chiếu đến cùng một vị trí bộ nhớ hay không. Nếu nó trả về True, điều đó có nghĩa là hai đối tượng thực sự là cùng một đối tượng. Tong đoạn code trên, thay vì tạo một bản sao mới khi y được gán cho một chuỗi có cùng giá trị với x, Python trỏ đến cùng một chuỗi được gán cho x. Điều này chỉ đúng với các chuỗi nhỏ hơn; các chuỗi lớn hơn sẽ tạo các bản sao riêng lẻ như bình thường.

Điều này sẽ in ra False trên console và các chuỗi không được interning. Và dưới đây là giải pháp:

5. 0.1+0.2 is not 0.3

Trong thực tế thì mọi người đều biết là0.1 + 0.2 = 0.3 tuy nhiên thì Python lại không nghĩ như vậy:

Thực tế mà nói, đây không phải là lỗi của Python. Không máy tính nào có thể tính toán giá trị float một cách chính xác.

Máy tính chỉ có thể lưu trữ và xử lý các số thực với độ chính xác nhất định. Vì vậy, các hoạt động của float dựa vào việc triển khai phần cứng trong chip xử lý của máy và không có ngôn ngữ lập trình nào có thể chắc chắn rằng các phép tính với float luôn được tính đúng.

Nguồn:

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo