Python Hàm Lambda với VÍ DỤ

Hàm Lambda là gì Python?

A Hàm Lambda trong Python lập trình là một hàm ẩn danh hoặc một hàm không có tên. Đây là một hàm nhỏ và bị hạn chế, không có nhiều hơn một dòng. Giống như hàm thông thường, hàm Lambda có thể có nhiều đối số với một biểu thức.

In Python, biểu thức lambda (hoặc biểu mẫu lambda) được sử dụng để xây dựng các hàm ẩn danh. Để làm như vậy, bạn sẽ sử dụng lambda từ khóa (giống như bạn sử dụng def để xác định các chức năng bình thường). Mọi hàm ẩn danh bạn xác định trong Python sẽ có 3 phần cơ bản:

  • Từ khóa lambda.
  • Các tham số (hoặc biến ràng buộc) và
  • Cơ thể chức năng.

Hàm lambda có thể có số lượng tham số bất kỳ, nhưng thân hàm chỉ có thể chứa một sự biểu lộ. Hơn nữa, lambda được viết bằng một dòng mã và cũng có thể được gọi ngay lập tức. Bạn sẽ thấy tất cả điều này được thực hiện trong các ví dụ sắp tới.

Cú pháp và ví dụ

Cú pháp chính thức để viết hàm lambda như sau:

lambda p1, p2: expression

Ở đây, p1 và p2 là các tham số được truyền cho hàm lambda. Bạn có thể thêm bao nhiêu hoặc ít tham số tùy thích.

Tuy nhiên, lưu ý rằng chúng ta không sử dụng dấu ngoặc xung quanh các tham số như chúng ta làm với các hàm thông thường. Phần cuối cùng (biểu thức) là bất kỳ biểu thức python hợp lệ nào hoạt động trên các tham số bạn cung cấp cho hàm.

Ví dụ 1

Bây giờ bạn đã biết về lambdas, hãy thử dùng một ví dụ. Vì vậy, hãy mở IDLE và nhập nội dung sau:

adder = lambda x, y: x + y
print (adder (1, 2))

Đây là đầu ra:

3

Giải thích mã

Ở đây, chúng ta xác định một biến sẽ chứa kết quả được hàm lambda trả về.

1. Từ khóa lambda được sử dụng để xác định hàm ẩn danh.

2. x và y là các tham số mà chúng ta truyền cho hàm lambda.

3. Đây là phần nội dung của hàm, bổ sung 2 tham số mà chúng ta đã truyền vào. Lưu ý rằng đó là một biểu thức duy nhất. Bạn không thể viết nhiều câu lệnh trong phần nội dung của hàm lambda.

4. Chúng ta gọi hàm và in giá trị trả về.

Ví dụ 2

Đó là một ví dụ cơ bản để hiểu các nguyên tắc cơ bản và cú pháp của lambda. Bây giờ chúng ta hãy thử in ra lambda và xem kết quả. Một lần nữa, hãy mở IDLE và nhập nội dung sau:

#What a lambda returns
string='some kind of a useless lambda'
print(lambda string : print(string))

Bây giờ hãy lưu tệp của bạn và nhấn F5 để chạy chương trình. Đây là đầu ra bạn sẽ nhận được.

Đầu ra:

<function <lambda> at 0x00000185C3BF81E0>

Chuyện gì đang xảy ra ở đây vậy? Hãy nhìn vào mã để hiểu thêm.

Giải thích mã

  1. Ở đây, chúng tôi định nghĩa một chuỗi mà bạn sẽ chuyển làm tham số cho lambda.
  2. Chúng ta khai báo một lambda gọi câu lệnh print và in kết quả.

Nhưng tại sao chương trình không in ra chuỗi ta truyền vào? Điều này là do chính lambda trả về một đối tượng hàm. Trong ví dụ này, lambda không được gọi là bằng chức năng in mà đơn giản là trở về đối tượng hàm và vị trí bộ nhớ nơi nó được lưu trữ. Đó là những gì được in ở bảng điều khiển.

Ví dụ 3

Tuy nhiên, nếu bạn viết một chương trình như thế này:

#What a lambda returns #2
x="some kind of a useless lambda"
(lambda x : print(x))(x)

Và chạy nó bằng cách nhấn F5, bạn sẽ thấy kết quả như thế này.

Đầu ra:

some kind of a useless lambda

Bây giờ, lambda đang được gọi và chuỗi chúng ta truyền được in ra tại bảng điều khiển. Nhưng cú pháp kỳ lạ đó là gì và tại sao định nghĩa lambda lại được bao phủ trong dấu ngoặc vuông? Chúng ta hãy cùng tìm hiểu ngay bây giờ.

Giải thích mã

  1. Đây là chuỗi tương tự mà chúng ta đã xác định trong ví dụ trước.
  2. Trong phần này, chúng ta định nghĩa lambda và gọi nó ngay lập tức bằng cách chuyển chuỗi làm đối số. Đây được gọi là IIFE và bạn sẽ tìm hiểu thêm về nó trong các phần sắp tới của hướng dẫn này.

Ví dụ 4

Hãy xem ví dụ cuối cùng để hiểu cách thực thi lambda và các hàm thông thường. Vì vậy, hãy mở IDLE và trong một tập tin mới, nhập nội dung sau:

#A REGULAR FUNCTION
def guru( funct, *args ):
funct( *args )
def printer_one( arg ):
return print (arg)
def printer_two( arg ):
print(arg)
#CALL A REGULAR FUNCTION 
guru( printer_one, 'printer 1 REGULAR CALL' )
guru( printer_two, 'printer 2 REGULAR CALL \n' )
#CALL A REGULAR FUNCTION THRU A LAMBDA
guru(lambda: printer_one('printer 1 LAMBDA CALL'))
guru(lambda: printer_two('printer 2 LAMBDA CALL'))

Bây giờ, lưu file và nhấn F5 để chạy chương trình. Nếu bạn không mắc lỗi nào thì kết quả sẽ như thế này.

Đầu ra:

printer 1 REGULAR CALL

printer 2 REGULAR CALL

printer 1 LAMBDA CALL

printer 2 LAMBDA CALL

Giải thích mã

  1. Một hàm có tên là guru, lấy một hàm khác làm tham số đầu tiên và bất kỳ đối số nào theo sau nó.
  2. print_one là một hàm đơn giản in tham số được truyền cho nó và trả về nó.
  3. print_two tương tự như print_one nhưng không có câu lệnh return.
  4. Trong phần này, chúng ta gọi hàm guru và truyền các hàm máy in và một chuỗi làm tham số.
  5. Đây là cú pháp để đạt được bước thứ tư (tức là gọi hàm guru) nhưng sử dụng lambdas.

Trong phần tiếp theo, bạn sẽ học cách sử dụng hàm lambda với bản đồ(), giảm bớt(),bộ lọc () in Python.

Sử dụng lambdas với Python tích hợp sẵn

Các hàm Lambda cung cấp một cách thanh lịch và mạnh mẽ để thực hiện các hoạt động bằng cách sử dụng các phương thức tích hợp trong Python. Điều này có thể xảy ra vì lambdas có thể được gọi ngay lập tức và được chuyển làm đối số cho các hàm này.

IIFE trong Python Lambda

IIFE là viết tắt của thực thi hàm được gọi ngay lập tức. Điều đó có nghĩa là hàm lambda có thể gọi được ngay khi được xác định. Hãy hiểu điều này bằng một ví dụ; cháy lên IDLE và nhập nội dung sau:

 (lambda x: x + x)(2)

Đây là đầu ra và giải thích mã:

Khả năng gọi ngay lập tức của lambda này cho phép bạn sử dụng chúng bên trong các hàm như map() và less(). Nó rất hữu ích vì bạn có thể không muốn sử dụng lại các chức năng này.

lambdas trong bộ lọc()

Hàm lọc được sử dụng để chọn một số phần tử cụ thể từ một chuỗi các phần tử. Trình tự có thể là bất kỳ trình vòng lặp nào như danh sách, bộ, bộ dữ liệu, v.v.

Các phần tử sẽ được chọn dựa trên một số ràng buộc được xác định trước. Phải mất 2 tham số:

  • Hàm xác định ràng buộc lọc
  • Một chuỗi (bất kỳ trình lặp nào như danh sách, bộ dữ liệu, v.v.)

Ví dụ,

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = filter (lambda x: x > 4, sequences) 
print(list(filtered_result))

Đây là đầu ra:

[10, 8, 7, 5, 11]

Giải thích mã:

1. Trong câu lệnh đầu tiên, chúng ta xác định một danh sách gọi là dãy chứa một số số.

2. Ở đây, chúng ta khai báo một biến có tên là filter_result, biến này sẽ lưu trữ các giá trị đã lọc được trả về bởi hàm filter().

3. Hàm lambda chạy trên từng phần tử của danh sách và trả về true nếu nó lớn hơn 4.

4. In kết quả trả về của hàm lọc.

lambdas trong bản đồ()

chức năng bản đồ được sử dụng để áp dụng một thao tác cụ thể cho mọi phần tử trong một chuỗi. Giống như filter(), nó cũng có 2 tham số:

  1. Một hàm xác định op để thực hiện trên các phần tử
  2. Một hoặc nhiều chuỗi

Ví dụ, đây là một chương trình in ra bình phương của các số trong một danh sách cho sẵn:

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = map (lambda x: x*x, sequences) 
print(list(filtered_result))

Đầu ra:

 [100, 4, 64, 49, 25, 16, 9, 121, 0, 1]

[KR1]

Giải thích mã:

  1. Ở đây, chúng tôi xác định một danh sách gọi là dãy chứa một số số.
  2. Chúng tôi khai báo một biến có tên là filter_result sẽ lưu trữ các giá trị được ánh xạ
  3. Hàm lambda chạy trên từng phần tử của danh sách và trả về bình phương của số đó.
  4. In kết quả được trả về bởi hàm bản đồ.

lambdas trong giảm()

Hàm rút gọn, như map(), được sử dụng để áp dụng một thao tác cho mọi phần tử trong một chuỗi. Tuy nhiên, nó khác với bản đồ trong cách hoạt động. Đây là các bước tiếp theo của hàm less() để tính toán kết quả đầu ra:

Bước 1) Thực hiện thao tác đã xác định trên 2 phần tử đầu tiên của chuỗi.

Bước 2) Lưu kết quả này

Bước 3) Thực hiện thao tác với kết quả đã lưu và phần tử tiếp theo trong chuỗi.

Bước 4) Lặp lại cho đến khi không còn phần tử nào nữa.

Nó cũng có hai tham số:

  1. Một hàm xác định thao tác sẽ được thực hiện
  2. Một chuỗi (bất kỳ trình lặp nào như danh sách, bộ dữ liệu, v.v.)

Ví dụ: đây là chương trình trả về tích của tất cả các phần tử trong danh sách:

from functools import reduce
sequences = [1,2,3,4,5]
product = reduce (lambda x, y: x*y, sequences)
print(product)

Đây là đầu ra:

120

Giải thích mã:

  1. Nhập giảm từ mô-đun functools
  2. Ở đây, chúng tôi xác định một danh sách gọi là dãy chứa một số số.
  3. Chúng tôi khai báo một biến có tên là sản phẩm sẽ lưu trữ giá trị giảm
  4. Hàm lambda chạy trên từng thành phần của danh sách. Nó sẽ trả về tích của số đó theo kết quả trước đó.
  5. In kết quả trả về của hàm less.

Tại sao (và tại sao không) sử dụng hàm lambda?

Như bạn sẽ thấy trong phần tiếp theo, lambda được xử lý giống như các hàm thông thường ở cấp độ trình thông dịch. Theo một cách nào đó, bạn có thể nói rằng lambdas cung cấp cú pháp nhỏ gọn để viết các hàm trả về một biểu thức.

Tuy nhiên, bạn nên biết khi nào nên sử dụng lambda và khi nào nên tránh chúng. Trong phần này, bạn sẽ tìm hiểu một số nguyên tắc thiết kế được các nhà phát triển python sử dụng khi viết lambdas.

Một trong những trường hợp sử dụng phổ biến nhất của lambdas là trong lập trình chức năng như Python hỗ trợ một mô hình (hoặc phong cách) lập trình được gọi là lập trình chức năng.

Nó cho phép bạn cung cấp một hàm làm tham số cho một hàm khác (ví dụ: trong bản đồ, bộ lọc, v.v.). Trong những trường hợp như vậy, việc sử dụng lambda là một cách hay để tạo hàm một lần và chuyển hàm đó làm tham số.

Khi nào thì không nên dùng Lambda?

Bạn không bao giờ nên viết các hàm lambda phức tạp trong môi trường sản xuất. Sẽ rất khó để các lập trình viên duy trì mã của bạn giải mã nó. Nếu bạn thấy mình đang tạo các biểu thức một dòng phức tạp, thì việc định nghĩa một hàm thích hợp sẽ là một cách thực hành tốt hơn nhiều. Theo cách thực hành tốt nhất, bạn cần nhớ rằng mã đơn giản luôn tốt hơn mã phức tạp.

Lambdas so với các hàm thông thường

Như đã nêu trước đây, lambdas là [vV4] [J5] chỉ là các hàm không có mã định danh được liên kết với chúng. Nói một cách đơn giản hơn, chúng là các hàm không có tên (do đó, ẩn danh). Đây là bảng minh họa sự khác biệt giữa lambdas và các hàm thông thường trong python.

thịt cừu

Chức năng thông thường

Cú pháp:

lambda x : x + x

Cú pháp:

def (x) :
return x + x 

Các hàm Lambda chỉ có thể có một biểu thức trong nội dung.

Các hàm thông thường có thể có nhiều biểu thức và câu lệnh trong phần thân của chúng.

Lambdas không có tên gắn liền với chúng. Đó là lý do tại sao chúng còn được gọi là hàm ẩn danh.

Các chức năng thông thường phải có tên và chữ ký.

Lambdas không chứa câu lệnh return vì phần thân được tự động trả về.

Các hàm cần trả về giá trị phải bao gồm câu lệnh return.

Giải thích sự khác biệt?

Sự khác biệt chính giữa hàm lambda và hàm thông thường là hàm lambda chỉ đánh giá một biểu thức duy nhất và tạo ra một đối tượng hàm. Do đó, chúng ta có thể đặt tên cho kết quả của hàm lambda và sử dụng nó trong chương trình của mình như đã làm trong ví dụ trước.

Một hàm thông thường cho ví dụ trên sẽ trông như thế này:

def adder (x, y):
return x + y 
print (adder (1, 2))

Ở đây chúng ta phải xác định một tên cho chức năng mà Trả về kết quả khi chúng ta cuộc gọi it. Một hàm lambda không chứa câu lệnh return vì nó sẽ chỉ có một biểu thức duy nhất luôn được trả về theo mặc định. Bạn thậm chí không cần phải gán lambda vì nó có thể được gọi ngay lập tức (xem phần tiếp theo). Như bạn sẽ thấy trong ví dụ sau, lambda trở nên đặc biệt mạnh mẽ khi chúng ta sử dụng chúng với Pythoncác chức năng tích hợp sẵn.

Tuy nhiên, bạn vẫn có thể thắc mắc lambda khác với hàm trả về một biểu thức đơn lẻ như thế nào (như biểu thức ở trên). Ở cấp độ thông dịch viên, không có nhiều khác biệt. Nghe có vẻ đáng ngạc nhiên, nhưng bất kỳ hàm lambda nào bạn xác định trong Python được trình thông dịch coi như một chức năng bình thường.

Như bạn có thể thấy trong sơ đồ, hai định nghĩa được trình thông dịch python xử lý theo cách giống nhau khi được chuyển đổi sang mã byte. Bây giờ, bạn không thể đặt tên cho một chức năng lambda bởi vì nó được bảo lưu bởi Python, nhưng bất kỳ tên hàm nào khác sẽ mang lại cùng mã byte[KR6].

Tổng kết

  • Lambdas, còn được gọi là hàm ẩn danh, là các hàm nhỏ, bị hạn chế và không cần tên (tức là mã định danh).
  • Mọi hàm lambda trong Python có 3 phần thiết yếu:
  • Từ khóa lambda.
  • Các tham số (hoặc biến ràng buộc) và
  • Cơ thể chức năng.
  • Cú pháp để viết lambda là: tham số lambda: biểu thức
  • Lambdas có thể có số lượng tham số bất kỳ, nhưng chúng không được đặt trong dấu ngoặc nhọn
  • Một lambda chỉ có thể có 1 biểu thức trong nội dung hàm của nó, được trả về theo mặc định.
  • Ở cấp độ bytecode, không có nhiều khác biệt giữa cách trình thông dịch xử lý lambda và các hàm thông thường.
  • Lambdas hỗ trợ IIFE thông qua cú pháp sau: (tham số lambda: biểu thức)(đối số)
  • Lambda thường được sử dụng với các hàm dựng sẵn sau của Python:
  • Bộ lọc: bộ lọc (tham số lambda: biểu thức, trình tự lặp)
  • Bản đồ: bản đồ (tham số lambda: biểu thức, chuỗi lặp)
  • Giảm: giảm (tham số lambda1, tham số2: biểu thức, chuỗi lặp)
  • Không viết các hàm lambda phức tạp trong môi trường sản xuất vì sẽ gây khó khăn cho người duy trì mã.

[J5]Tôi đã thêm một bảng nhưng cần phải giải thích để hiểu được sự khác biệt.