Học bằng cách đọc theo thứ tự

Biểu thức Lambda — Viết hàm vô danh trong một dòng

Học biểu thức lambda trong Python để viết hàm vô danh chỉ trong một dòng và kết hợp tự nhiên với các hàm bậc cao.

Trong bài trước về hàm bậc cao, bạn đã thấy cách truyền hàm như tham số và giá trị trả về. Định nghĩa một hàm mới bằng def mỗi khi cần truyền callback nghĩa là một thao tác một dòng đột nhiên mất 3 hay 4 dòng.

Đó là lúc biểu thức lambda (lambda) xuất hiện — chúng cho phép bạn viết một hàm vô danh trên một dòng duy nhất. Hoàn hảo cho những mảnh logic nhỏ không xứng đáng có cả một def.

Lambda là gì — So với def

Cú pháp là lambda args: biểu thức. Kết quả của biểu thức trở thành giá trị trả về trực tiếp, và bạn không viết return (thực ra, làm vậy sẽ kích hoạt SyntaxError).

Khác với hàm thông thường, lambda không có tên, nên không thể gọi trừ khi bạn gán nó vào biến. Tên biến bạn gán nó vào sẽ trở thành tên của hàm.

def vs Lambda đặt cạnh nhau
Phiên bản defdef add_tax(p): return int(p*1.1)Phiên bản lambdaadd_tax = lambda p: int(p*1.1)nén thành 1 dòng
Một hàm nhỏ tốn 4 dòng với def có thể viết trong 1 dòng với lambda. Không cần return — giá trị biểu thức sau : được trả về nguyên dạng.
# Viết bằng def
def add_tax(price):
    return int(price * 1.1)

print(add_tax(980))   # 1078

# Cùng logic dưới dạng lambda (không cần return)
add_tax = lambda price: int(price * 1.1)

print(add_tax(980))   # 1078

Chỉ cho phép biểu thức — Không có câu lệnh

Thân lambda chỉ chứa biểu thức (cái gì đó định trị thành một giá trị). Câu lệnh if, vòng lặp for, và phép gán (=) không vừa. Khoảnh khắc bạn muốn cái gì đó cầu kỳ hơn, quay lại def — đó là lựa chọn đúng.

Viết một hàm một dòng cộng 10% thuế bán hàng vào giá sản phẩm.

① Xây một hàm nhận giá và trả về số tiền đã bao gồm thuế dưới dạng số nguyên.

② Gọi nó với 980 yên và 2480 yên và in từng kết quả.

(Khi đáp án đúng, phần giải thích sẽ xuất hiện.)

Python Editor

Chạy code để xem đầu ra

Nhiều tham số, biểu thức điều kiện, và mặc định

Lambda cũng nhận nhiều tham số. Chỉ cần liệt kê chúng cách nhau bằng dấu phẩy, như lambda x, y: x * y.

Bạn cũng có thể dùng tham số mặc định giống như với def. Để đổi giá trị dựa trên điều kiện, đặt một biểu thức điều kiện value1 if condition else value2 vào thân.

# Nhiều tham số
rect_area = lambda width, height: width * height
print(rect_area(4, 5))            # 20

# Tham số mặc định (bỏ rate để dùng 0.1)
add_tax = lambda price, rate=0.1: int(price * (1 + rate))
print(add_tax(1000))              # 1100
print(add_tax(1000, 0.08))        # 1080

# Biểu thức điều kiện
judge_age = lambda age: "người lớn" if age >= 20 else "trẻ vị thành niên"
print(judge_age(25))              # người lớn
print(judge_age(17))              # trẻ vị thành niên

# Trả về nhiều giá trị dưới dạng tuple
stats = lambda x, y: (x + y, x * y)
print(stats(3, 4))                # (7, 12)
Các biến thể tham số của Lambda
lambda x, y: x * yNhiều tham sốlambda x, y=2: x**yTham số mặc địnhlambda x: "+" if x>0 else "-"Biểu thức điều kiện
lambda xử lý nhiều tham số, tham số mặc định, và rẽ nhánh với biểu thức điều kiện với cảm giác giống def.

Viết một dòng trả về hạng thành viên (GOLD / SILVER / BRONZE) dựa trên điểm. 1000 trở lên được GOLD, 500 trở lên được SILVER, ít hơn là BRONZE.

① Xây một hàm nhận điểm và trả về hạng.

② Gọi nó với 1500, 700, và 100, và in kết quả cho từng cái.

Python Editor

Chạy code để xem đầu ra

Kết hợp với hàm bậc cao — Nơi Lambda tỏa sáng

Lambda thực sự kiếm được giá trị khi bạn muốn trao một hàm dùng-một-lần cho hàm bậc cao. Ví dụ, tham số key của sorted() là một hàm bậc cao nhận "một hàm trả về khóa sắp xếp từ mỗi phần tử."

Với một thứ tự sắp xếp bạn không cần đặt tên và dùng lại, viết key=lambda x: x["price"] inline tại chỗ gọi là dạng tự nhiên nhất.

products = [
    {"name": "Vở",   "price": 480},
    {"name": "Bút",  "price": 120},
    {"name": "Tẩy",  "price": 80},
]

# Sắp xếp theo giá tăng dần (truyền lambda inline làm key)
cheap_first = sorted(products, key=lambda item: item["price"])
for item in cheap_first:
    print(item["name"], item["price"])
# Tẩy 80
# Bút 120
# Vở 480

# Cùng hàm bậc cao process_list có thể đổi hành vi qua lambda
def process_list(numbers, func):
    for n in numbers:
        print(func(n))

process_list([1, 2, 3, 4], lambda x: x ** 2)
# 1
# 4
# 9
# 16
Cách Lambda chảy vào key của sorted
products(list các dict)key=lambda item: item["price"]List mới sắp xếptheo giá tăng dầnáp dụng cho từng itemsắp xếp theo giá trị key

Sắp xếp một list user theo điểm, cao nhất trước. sorted() chuyển thành giảm dần khi bạn truyền reverse=True.

① Định nghĩa users = [{"name": "Minh", "score": 78}, {"name": "Linh", "score": 92}, {"name": "Nam", "score": 65}].

② Sắp xếp với sorted(users, key=lambda u: u["score"], reverse=True) và gán kết quả vào ranking.

③ Lặp với for u in ranking: và in print(u["name"], u["score"]).

Python Editor

Chạy code để xem đầu ra

Khi nào dùng Lambda — và khi nào tránh

Lambda tiện lợi, nhưng dùng chúng ở khắp nơi thực ra làm tổn hại tính dễ đọc. Bảng dưới tổng hợp: tìm đến lambda cho thao tác một lần, một dòng, và giữ def cho bất cứ thứ gì phức tạp hoặc dùng lại.

Tình huốngKhuyến nghịLý do
Truyền cho key của sorted, filter, maplambdaMột dòng truyền tải ý định; không cần đặt tên
Biểu thức một dòng như giá đã thuếlambdaHàm có tên ngắn không cần import
Logic cần if / for / trydeflambda chỉ là biểu thức; câu lệnh phát sinh SyntaxError
Logic dùng lại từ nhiều nơidefTên truyền tải ý định và hỗ trợ test, doc
Thân chạy 3+ dòngdefNhồi vào lambda chỉ làm tổn hại tính dễ đọc

Đừng nhồi mọi thứ vào Lambda

Xếp ba biểu thức điều kiện lồng nhau hoặc nối vài lệnh gọi hàm với nhau và bạn rốt cuộc có code trên một dòng nhưng không đọc được. Khoảnh khắc bạn nghĩ "Tôi muốn để lại comment giải thích lambda này làm gì," hãy với tay tới def thay vào đó.

Truyền một lambda inline cho hàm bậc cao gọi là process_list.

① Định nghĩa def process_list(numbers, func): và gọi print(func(n)) bên trong for n in numbers:.

② Gọi process_list([1, 2, 3, 4, 5], lambda x: x ** 2) và xác nhận bình phương của từng phần tử in theo thứ tự.

③ Gọi lại với process_list([1, 2, 3, 4, 5], lambda x: x * 10) và xác nhận hành vi đổi chỉ bằng cách đổi lambda.

Python Editor

Chạy code để xem đầu ra
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Cái nào dưới đây là biểu thức lambda hợp lệ?

Câu 2Code này in gì?
f = lambda x, y=3: x ** y
print(f(2))

Câu 3Cái nào dưới đây là cách dùng phù hợp nhất của biểu thức lambda?