Biến, kiểu dữ liệu và toán tử trong Python

Biến và kiểu dữ liệu là nền tảng của mọi chương trình Python. Bài này đi qua những gì bạn thực sự cần nắm, kèm theo vài điểm mà người mới hay hiểu sai.

Biến trong Python là gì?

Khác với C hay Java, Python không yêu cầu khai báo kiểu. Bạn gán giá trị và Python tự xác định kiểu:

ten = "Minh"
tuoi = 25
diem = 8.5
da_tot_nghiep = True

Điểm quan trọng: trong Python, biến không phải là “cái hộp chứa giá trị” mà là cái nhãn gắn vào một đối tượng. Hiểu điều này giúp bạn tránh được một lớp lỗi khá khó chịu:

a = [1, 2, 3]
b = a
b.append(4)
print(a)    # [1, 2, 3, 4] — a cũng đổi theo!

Ở đây ab là hai cái nhãn cùng gắn vào một danh sách. Muốn có bản sao độc lập, bạn phải tạo rõ ràng:

b = a.copy()        # hoặc b = list(a)

Các kiểu dữ liệu cơ bản

Số

Python có ba kiểu số: int, floatcomplex. Số nguyên trong Python không giới hạn độ lớn — bạn có thể tính giai thừa của 1000 mà không tràn số:

print(2 ** 100)
# 1267650600228229401496703205376

Số thực thì khác. float tuân theo chuẩn IEEE 754, nên có sai số làm tròn:

print(0.1 + 0.2)          # 0.30000000000000004
print(0.1 + 0.2 == 0.3)   # False

Đây không phải lỗi của Python mà là bản chất của số thực dấu phẩy động. Khi làm việc với tiền tệ hoặc cần chính xác tuyệt đối, hãy dùng Decimal:

from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))   # 0.3

Chuỗi

Chuỗi trong Python là bất biến — bạn không thể sửa một ký tự trong chuỗi đã tạo. Mọi thao tác “thay đổi” đều tạo ra chuỗi mới.

s = "Xin chào"
print(s.upper())        # XIN CHÀO
print(s[0])             # X
print(s[-1])            # o
print(s[4:])            # hào

Cách nối chuỗi hiện đại và dễ đọc nhất là f-string:

ten = "Lan"
tuoi = 30
print(f"{ten} năm nay {tuoi} tuổi")
print(f"Sang năm: {tuoi + 1}")
print(f"Số pi: {3.14159:.2f}")     # Số pi: 3.14

Boolean và None

Python coi nhiều giá trị là “sai” trong ngữ cảnh điều kiện: 0, chuỗi rỗng, danh sách rỗng, None, và False. Tất cả những thứ còn lại đều là “đúng”.

if not danh_sach:
    print("Danh sách rỗng")

None là một giá trị riêng biệt, dùng để biểu thị “không có giá trị”. Khi so sánh với None, hãy dùng is chứ không dùng ==:

if ket_qua is None:
    print("Chưa có kết quả")

Toán tử

Ngoài các phép tính quen thuộc, Python có vài toán tử đáng chú ý:

print(7 / 2)      # 3.5    — chia thường, luôn ra float
print(7 // 2)     # 3      — chia lấy phần nguyên
print(7 % 2)      # 1      — chia lấy dư
print(7 ** 2)     # 49     — lũy thừa

Một điểm khiến người đến từ ngôn ngữ khác bất ngờ: Python cho phép so sánh liên tiếp một cách tự nhiên.

tuoi = 25
if 18 <= tuoi < 60:
    print("Trong độ tuổi lao động")

Chuyển đổi kiểu

Python không tự động chuyển kiểu giữa số và chuỗi, nên đoạn dưới sẽ báo lỗi:

print("Tuổi: " + 25)    # TypeError

Bạn phải chuyển đổi rõ ràng:

print("Tuổi: " + str(25))
print(int("25") + 5)
print(float("3.14"))

Khi dữ liệu đến từ người dùng hoặc file, hãy luôn phòng trường hợp không chuyển đổi được:

try:
    n = int(input("Nhập số: "))
except ValueError:
    print("Đó không phải số hợp lệ")

Gợi ý kiểu dữ liệu

Python vẫn là ngôn ngữ động, nhưng từ phiên bản 3.5 bạn có thể ghi chú kiểu để code dễ đọc và công cụ kiểm tra bắt lỗi sớm hơn:

def tinh_diem_trung_binh(diem: list[float]) -> float:
    return sum(diem) / len(diem)

Những ghi chú này không ràng buộc khi chạy — Python không chặn bạn truyền sai kiểu. Chúng phát huy tác dụng khi bạn dùng công cụ như mypy để kiểm tra tĩnh, hoặc đơn giản là giúp đồng nghiệp đọc code hiểu ngay ý định của bạn.