Chuyển đến nội dung chính

Hướng dẫn Kiểm tra Kiểu dữ liệu trong Python

Tìm hiểu về kiểm tra kiểu dữ liệu, các loại hệ thống kiểu trong nhiều ngôn ngữ cùng với duck typing và gợi ý kiểu.
· 7 phút đọc

Khám phá cùng AI

Bản thân Trình thông dịch của Python hỗ trợ kiểm tra kiểu dữ liệu. Vì Python là một ngôn ngữ động, nó không bắt buộc người dùng phải áp đặt kiểu của đối tượng, điều này có thể dẫn đến lỗi và khó phát hiện. Để khắc phục, Python có thể được dùng cùng với nhiều công cụ khác và triển khai các tính năng của kiểm tra kiểu tĩnh song song với Duck Typing của chính nó.

Có hai loại hệ thống kiểu dữ liệu khác nhau được các ngôn ngữ lập trình áp dụng, như dưới đây.

    1. Ngôn ngữ kiểu tĩnh
    2. Ngôn ngữ kiểu động

Ngôn ngữ kiểu tĩnh

Việc kiểm tra kiểu của biến được thực hiện tại thời điểm biên dịch. Đồng thời, hệ thống kiểu của ngôn ngữ buộc phải khai báo rõ ràng 'kiểu dữ liệu' của biến trước khi sử dụng. Các ngôn ngữ lập trình được kiểu tĩnh gồm: Scala, Java, C++, v.v.
Ví dụ, khai báo String trong Scala được định nghĩa như dưới đây:
var myCar:String = "Mercedes";
Đoạn mã trên cho thấy biến 'myCar' được khai báo rõ ràng có kiểu dữ liệu 'String' với giá trị là 'Mercedes'.

Ngôn ngữ kiểu động

Việc kiểm tra kiểu của biến được thực hiện tại thời điểm chạy. Đồng thời, hệ thống kiểu của ngôn ngữ không buộc phải khai báo rõ ràng 'kiểu dữ liệu' của biến trước khi sử dụng. Các ngôn ngữ lập trình kiểu động gồm: Python, Javascript, Ruby, v.v.
Ví dụ, String trong Python được định nghĩa như dưới đây:
myCar = "Mercedes"
Đoạn mã trên cho thấy biến 'myCar' không cần phải khai báo rõ ràng.

'type()' và 'isinstance()' trong Python

Có thể biết kiểu của biến bằng 'type()' của chính Python. 'type()' có thể được dùng tại thời điểm chạy cho mục đích gỡ lỗi để xác định chính xác kiểu biến trong chương trình. Hãy xem kiểu của một số biến trong ví dụ dưới đây.

my_var = 12
print(type(my_var))

Đoạn mã trên sẽ cho đầu ra là 'int'. Vì kiểu dữ liệu của biến là số nguyên, 'type()' đóng vai trò xác định điều đó.

'insinstance('obj','class')' của Python có thể dùng để biết liệu 'obj' (đối tượng) có phải là một thể hiện của lớp hay không. Giá trị trả về là boolean, có thể là True hoặc False.

my_var = "Hello"
print(isinstance(my_var,str))

Đoạn mã trên sẽ cho đầu ra là True. Vì kiểu dữ liệu của biến là chuỗi, 'isinstance()' đóng vai trò xác định điều đó.

Duck typing trong Python

Có một nguyên lý phổ biến trong Python: "Nếu nó trông như vịt, bơi như vịt và kêu như vịt, thì có lẽ nó là vịt." Đơn giản là nguyên lý này nói rằng kiểu của đối tượng hay lớp không quan trọng, mà đối tượng cần có các phương thức và thuộc tính tương tự, khi đó đối tượng có thể được dùng cho một mục đích cụ thể.
Hãy xem một ví dụ để làm rõ hơn nhận định trên.

Xem ví dụ dưới đây, có hai lớp 'Duck' và 'Human'. Duck là lớp chứa các phương thức quack và fly. Tương tự, Human là một lớp với bộ phương thức riêng 'quack' và 'fly'. Duck và Human là các lớp khác nhau và cũng là các đối tượng/kiểu khác nhau. Tuy nhiên, Human có các phương thức tương tự 'fly' và 'quack' như Duck. Cũng có một hàm 'fly_quack', vốn giống với 'Duck' hơn 'Human' vì nó có thể gọi fly và quack.

class Duck:
    def quack(self):
        print('Quack')
    def fly(self):
        print('Flap')
class Human:
    def quack(self):
        print('Trying to Quack like a duck')
    def fly(self):
        print('Spreading my arm to flap like a duck')      
def fly_quack(thing):
    thing.quack()
    thing.fly()

Hãy tạo một thể hiện của 'Duck' là du và truyền vào hàm 'fly_quack(du)'. Tương tự, tạo thể hiện của Human là 'h' và truyền vào hàm 'fly_quack(h)'.

du = Duck()
fly_quack(du)
h = Human()
fly_quack(h)

Kết quả đầu ra của đoạn mã trên như dưới đây:

Trying to Quack like a duck
Spreading my arm to flap like a duck
Quack
Flap

Mặc dù lớp 'Human' khác với 'Duck', Python vẫn gọi hàm 'fly_quack' cho human. Dù kiểu đối tượng khác nhau, vì 'Human' có các phương thức quack và fly tương tự, nó hoạt động và cung cấp các phương thức cần thiết.

Type hint và mypy

Có một khía cạnh mạnh mẽ của ngôn ngữ kiểu động như Python giúp mã dễ truy cập và dễ đọc, nhưng cũng có một số hạn chế. Một trong số đó là khó tìm lỗi thời gian chạy vì Python không áp đặt kiểu của biến, hay nói cách khác là ngôn ngữ kiểu động. Hệ quả là có thể phát sinh lỗi và bug, khó phát hiện khi độ dài mã ngày càng lớn.

Python đã triển khai Type Hints từ phiên bản 3.5. Các phiên bản cũ hơn có thể không hỗ trợ chức năng TypeHints.

Bạn sẽ thấy ví dụ đơn giản không dùng type hinting và mypy.

Hàm dưới đây để thực hiện phép trừ số nguyên, trừ hai số nguyên và trả về giá trị.

def sub_this(x,y):
    return 'Subtraction'
print(sub_this(8,'hello'))

Ở đây, hàm trên cần nhận hai số nguyên 'x' và 'y', nhưng do không có ràng buộc, nó có thể nhận bất kỳ kiểu dữ liệu nào. Ngoài ra, giá trị trả về có thể là bất cứ thứ gì, ở đây trả về 'str' ('Subtraction') trong khi kỳ vọng là 'int'.

Hãy xem cách triển khai tương tự cho chương trình trên nhưng dùng type hints và 'mypy', có thể giúp thực hiện kiểm tra kiểu tĩnh và giảm lỗi, bug trong chương trình khá dễ dàng.

'mypy' là một mô-đun Python hỗ trợ kiểm tra kiểu tĩnh, kết hợp kiểm tra động/duck typing của chính Python với gợi ý kiểu (type hinting).

Bạn cần cài đặt gói 'mypy'
pip install mypy

Bạn có thể tạo một tệp tên 'mypy_example.py' trên máy và nhập đoạn mã sau.
Đoạn mã dưới đây là một chương trình đơn giản nhận hai số nguyên làm tham số đầu vào và sau '->' cho biết kiểu dữ liệu trả về, cũng là 'int'. Tuy nhiên, hàm cần trả về int, nhưng lại trả về chuỗi 'Subtracted two integers'.

def sub_this(x:int,y:int) -> int:
    return 'Subtracted two integers'
print(sub_this(8,4))

Chạy đoạn mã trên trong terminal với lệnh sau.

mypy mypy_example.py

Sau đó sẽ hiển thị lỗi cho biết tìm thấy giá trị trả về không mong đợi "str" và cần được sửa thành "int".

Error message

Hãy thay đổi kiểu trả về thành phép trừ của hai số nguyên để trả về giá trị số nguyên.

def sub_this(x:int,y:int) -> int:
    return x - y
print(sub_this(8,4))

Success message

Kết quả trên cho thấy thông báo thành công được in ra và không phát hiện vấn đề nào.

Chúc mừng

Chúc mừng bạn đã hoàn thành bài hướng dẫn này!

Trong bài hướng dẫn này, bạn đã học về kiểm tra kiểu dữ liệu, các loại hệ thống kiểu trong nhiều ngôn ngữ cùng với các phương thức của Python ('type()' và 'isinstance()'), duck typing trong Python và gợi ý kiểu kết hợp với 'mypy'.

Nếu bạn muốn học thêm về Python, hãy tham gia khóa Software Engineering for Data Scientists in Python của DataCamp.

Tài liệu tham khảo:

  1. Video Duck Typing của Corey trên Youtube

Chủ đề

Liên quan