Hướng dẫn add annotation in python

Hy vọng các bạn đã đọc và áp dụng được các mẹo sử dụng hàm trong python ở bài viết trước của mình. Các mẹo sử dụng hàm rất nhiều, nhưng chúng ta sẽ tập trung vào những phân thông dụng nhất.

Chú ý:

Để hiểu các bài viết trong loạt bài này, bạn nên có các kiến thức về lập trình với ngôn ngữ python, nếu bạn chưa rõ về python và muốn tìm hiểu nó, thì mình đề xuất các bạn đọc các khóa học lập trình cơ bản với python, trước khi đọc các bài viết trong loạt bài này. Khóa học về python cơ bản bạn có thể tìm thấy ở đây.

Để tiếp tục với loạt bài mẹo sử dụng python hiệu quả, hôm nay mình sẽ giới thiệu tới các bạn một điều khá thú vị và mới mẻ trong python, đó là khái niệm 'type annotations'. Cái này là cái mới được đưa vào và chỉ có với phiên bản python lớn hơn 3.5. Các bạn chú ý là để chạy ví dụ trong bài viết này cũng cần đảm bảo là bạn đã cài python3 với version >=3.5 nhé.

Hướng dẫn cài đặt python3 trên windows 10 ở đây.

Còn nếu trên linux thì bạn làm theo hướng dẫn này.

Quay trở lại với nội dung chính của bài để nói về 'type annotations', chúng ta cùng đi tìm hiểu các vấn đề: nó là gì,dùng để làm gì, và khi nào thì cần dùng/nên dùng đến nó?

 

Type annotations là gì?

 

Trong C hay Java, khi khai báo một biến ta luôn phải chỉ ra kiểu dữ liệu tương ứng của biến đó. ví dụ khai báo một biến nguyên tên a trong C và gán cho nó giá trị bằng 20 ta phải làm như sau;

int a = 20;

Nhưng với python ta chỉ đơn thuần làm như sau:

a = 20

Diều này có nghĩa là trong python ta không cần khai báo kiểu dữ liệu cho biến. Chính điều này dẫn tới một số trường hợp như sau: giả sử ta có hàm như sau (mục đích của hàm này là trả về tổn của hai số nguyên):

def func( a, b):
        return a+b

Giờ ta sẽ gọi hàm trên:

a1 = 2
b1 = 'abcxyz'

func(a1, b1)

Khi chạy hàm này bạn sẽ gặp lỗi “TypeError: unsupported operand type(s) for +: 'int' and 'str'”, đúng vậy, làm sao có thể cộng một số nguyên với một chuỗi được!

Vấn đề ở đây là, trước khi hàm func thực sự chạy, ta không biết được rằng ta đã truyền sai kiểu biến vào hàm. Giả sử ta biến đổi hàm func như sau;

def func1( a, b):
        import time
        time.sleep(20) # Delay trong vòng 20 giây
        return a+b

Rồi vẫn gọi hàm func1 giống như cách ta đã gọi hàm func

a2 = 2
b2 = 'abcxyz'

func1(a2, b2)

Lúc này bạn có thể để ý thấy rằng phải mất 20 giây sau bạn mới nhận được thông báo lỗi “TypeError: unsupported operand type(s) for +: 'int' and 'str'”.

Điều này thật không tốt, nếu bạn nhận được thông báo ngay từ khi bạn truyền biến vào các hàm trên thì sẽ tốt biết mấy, hoặc khi bạn truyền tham số vào hàm mà có một gợi ý cho bạn biết nên truyền vào tham số kiểu gì thì sẽ còn tốt hơn nhiều nữa.

Và trong python với type annotations chúng ta sẽ có được điều đó.

 

Cách sử dụng type annotations

 

Để sử dụng type annotations ta sử dụng cú pháp như sau.

 : 

 -> 

Từ khóa đứng sau dấu ‘:’ và ‘->’  chính là kiểu dữ liệu mà ta đang thực hiện type annotations.

Hãy cùng viết lại hàm func1 như sau;

def func2(a: int, b: int) -> int:
       import time
       time.sleep(20) # Delay trong vòng 20 giây
       return a + b

Và thực hiện lời gọi hàm:

a3 = 2
b3 = 'abcxyz'

func2(a3, b3)

Nếu bạn chạy ví dụ trên trực tiếp trên terminal của python, bạn sẽ không thấy gì khác biệt khi thực thi func1 và func2, nhưng nếu bạn dùng IDE như Pycharm chẳng hạn, nó sẽ đưa cho bạn luôn một cảnh báo: “Expected type 'int', got 'str' instead”.

Nếu bạn ngại cài đặt pycharm để kiểm chứng ví dụ này, bạn cũng có thể dùng một tool có tên là Mypy để kiểm tra trước các lỗi về kiểu dữ liệu:

Để cài đặt Mypy trên ubuntu dung lệnh sau:

sudo apt install python3-distutils
sudo apt-get install mypy

Tạo file type-annotations.py với nội dung như sau:

def func2(a: int, b: int) -> int:
    import time
    time.sleep(20)
    return a + b

a3 = 2
b3 = 'abcxyz'

func2(a3, b3)

Sau đó bật terminal và chạy lệnh:

mypy type-annotations.py

Ta sẽ thấy thông báo như sau

test-annotations.py:10: error: Argument 2 to "func2" has incompatible type "str"; expected "int"

Kết luận

Không ai ép bạn phải dùng type annotations, nhưng từ những lợi ích mà nó đem lại tại sao bạn không thử để giúp code của bạn hoàn thiện hơn, nhờ đó các IDE cũng có thể  hỗ trợ bạn tốt hơn bằng việc đưa ra các gợi ý trong khi bạn viết code.

Mình thường hay chạy test với mypy cho chương trình của mình sau mỗi lần chạy unit test. Nó giúp bạn tiết kiệm thời gian vì các bug có thể được phát hiện và xử lý sớm hơn.