Tại sao Python là một ngôn ngữ lập trình chức năng?

Trong bài viết này, chúng ta sẽ tìm hiểu khái niệm về lập trình hàm, bao gồm cả sự khác biệt của nó với lập trình hướng đối tượng

Bài viết này được chia thành các phần sau

Giới thiệu về lập trình chức năng

Lập trình hàm là một mô hình lập trình trong đó mã được cấu trúc chủ yếu dưới dạng các hàm. Nguồn gốc của phong cách lập trình này phát sinh từ một nhánh toán học được gọi là phép tính lambda, là nghiên cứu về các hàm và tính chất toán học của chúng. Trái ngược với các cách tiếp cận thủ tục và hướng đối tượng phổ biến, lập trình hàm cung cấp một cách suy nghĩ khác khi giải quyết vấn đề

Hãy khám phá cách lập trình các giải pháp theo kiểu chức năng bằng Python

chức năng so với. lập trình hướng đối tượng

Trong lập trình hướng đối tượng [OOP], bạn cấu trúc mã của mình dựa trên khái niệm về đối tượng. Trong các ngôn ngữ OOP thường được sử dụng [chẳng hạn như Java hoặc C#], chúng tôi tạo mẫu cho một đối tượng bằng cách sử dụng từ khóa class và chúng tôi khởi tạo một đối tượng bằng cách sử dụng từ khóa new. Các đối tượng này chứa các trường lưu trữ dữ liệu và các phương thức thao tác dữ liệu. Trong phong cách này, một đối tượng có thể được truyền dưới dạng đối số trong hàm của một đối tượng khác

Trong lập trình chức năng, bạn tạo một giải pháp bằng cách cấu trúc mã chủ yếu sử dụng các chức năng. Các hàm là “công dân hạng nhất” trong mô hình này, nghĩa là chúng ta có thể sử dụng chúng để lưu trữ và thao tác dữ liệu [có giới hạn]. Tương tự như các đối tượng trong lập trình hướng đối tượng, trong lập trình hàm, các hàm có thể được truyền vào dưới dạng đối số cho các hàm khác và có thể được trả về bởi các hàm khác

Tuyên bố vs. lập trình bắt buộc

Trước khi tìm hiểu về những lợi thế mà lập trình chức năng mang lại, trước tiên chúng ta phải thảo luận về sự khác biệt giữa mô hình bắt buộc và mô hình khai báo

Lập trình mệnh lệnh giải quyết vấn đề bằng cách mô tả giải pháp từng bước. Lập trình mệnh lệnh liên quan đến “làm thế nào để giải quyết một vấn đề. ”

Ngược lại, lập trình khai báo dựa trên khung hoặc ngôn ngữ lập trình cơ bản để giải quyết vấn đề. Nhiệm vụ duy nhất của lập trình viên là mô tả vấn đề họ muốn giải quyết. Lập trình khai báo liên quan đến vấn đề “giải quyết vấn đề gì. ”

Tương tự như vậy, hãy xem xét ví dụ về việc lấy một tách cà phê. Lập trình bắt buộc sẽ tương đương với việc bạn tự pha một tách cà phê bằng cách thực hiện các bước sau

  • Lấy bình cà phê của bạn ra
  • Cho bã cà phê vào nồi
  • Thêm nước vào bình cà phê
  • Đặt ấm cà phê lên bếp
  • Bật bếp
  • Chờ cho đến khi cà phê được thực hiện
  • Rót cà phê vào cốc
  • Bạn có thích đường không?
    • Nếu có, thêm đường
    • Nếu không, không thêm đường
  • Uống cà phê

Lập trình khai báo tương đương với việc bạn đến quán cà phê gần nhà và nói với nhân viên pha chế, “Tôi muốn một tách cà phê với một thìa cà phê đường, vui lòng. ” Nhân viên pha cà phê chuẩn bị cà phê cho bạn, đưa cho bạn tách cà phê và bạn uống nó mà không cần quan tâm đến chi tiết nó được pha như thế nào

Đối với một phép tương tự trong lập trình, hãy xem xét ví dụ về việc phải sắp xếp một danh sách trong Python. Việc sắp xếp danh sách theo cách bắt buộc sẽ là bạn thực hiện một thuật toán sắp xếp như thế này

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

for j in range[i+1, len[lst]]:

min_idx = j if lst[j] < lst[min_idx] else min_idx

Nếu chúng ta giải quyết danh sách theo cách khai báo bằng Python, chúng ta sẽ gọi hàm list.sort[] như vậy

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

Lập trình viên theo phong cách nào có thể phụ thuộc vào mục tiêu của họ. Nếu bạn đang tìm kiếm mã ngắn gọn giúp bạn có câu trả lời hiệu quả, bạn có thể sử dụng cách tiếp cận mang tính khai báo hơn. Nếu bạn đang làm việc với những người khác và muốn đảm bảo rằng mã của bạn dễ theo dõi, bạn có thể chọn kiểu bắt buộc hơn

OOP và lập trình thủ tục tuân theo một cách tiếp cận bắt buộc;

Viết hàm trong lập trình hàm

Như chúng tôi đã nói trong phần giới thiệu của bài viết này, khái niệm trung tâm trong lập trình hàm là hàm; . Yêu cầu đầu tiên là chức năng phải xác định. Nghĩa là, đối với bất kỳ đầu vào cụ thể nào, hàm phải trả về cùng một đầu ra khi được cung cấp cùng một bộ đầu vào. Hãy minh họa điều này bằng ví dụ sau về hàm add

Hàm này sẽ luôn trả về 7 nếu add[5, 2] được gọi

Một trong những yêu cầu này là các chức năng phải không có càng nhiều tác dụng phụ càng tốt. Tác dụng phụ là khi một chức năng thay đổi một số biến bên ngoài. Mục tiêu là để giảm thiểu, không loại bỏ, tác dụng phụ. Sẽ không thể loại bỏ tất cả các hiệu ứng phụ trong một chức năng bởi vì một chương trình cuối cùng phải có hiệu ứng bên ngoài để hữu ích

Một hàm thuần túy được định nghĩa là một hàm xác định không có tác dụng phụ

Hãy xem xét ví dụ này

Hàm add[x, y] được xác định theo cách này có tác dụng phụ vì nó thay đổi biến ngoài

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

0

Để biến đây thành một hàm thuần túy, chúng ta nên viết nó dưới dạng

Lưu ý cách hàm add[x, y] không còn thay đổi biến

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

0 trong khi thực thi. Ngoài ra, các biến

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

3 và

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

4 chỉ tồn tại trong phạm vi của hàm. Hoạt động trên chúng cho phép chức năng không có tác dụng phụ

Để có thể sử dụng lại, một hàm phải luôn có tất cả các tham số liên quan được truyền vào và không nên dựa vào các biến toàn cục

Xem xét ví dụ về hàm [

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

5] thay thế phần tử đầu tiên và cuối cùng của danh sách bằng

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

6

Viết một hàm theo cách này khiến nó phụ thuộc vào một biến danh sách bên ngoài có tên là

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

7. Không thể sử dụng lại chức năng này vì sử dụng nó ở nơi khác yêu cầu phải xác định bên ngoài

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

7. Mặc dù nó không thể tái sử dụng, nhưng biến

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

5 vẫn được coi là không có tác dụng phụ khi nó đọc, nhưng không sửa đổi, biến

lst = [8, 4, 14, 9, 12, 5, 7, 1, 10, 2, 3]

7. Một cách tốt hơn để viết hàm là chuyển vào biến danh sách được yêu cầu dưới dạng đối số như vậy

Chức năng

def recursive_function[n]:

1 không có tác dụng phụ và hiện cũng có thể tái sử dụng

Chúng tôi quan tâm đến các hàm thuần túy vì khi các chương trình của chúng tôi trở nên phức tạp hơn, chúng tôi muốn tránh những thay đổi không chính xác của các biến bên ngoài. Ví dụ: nếu chúng ta gọi các hàm từ các luồng khác nhau đang chạy đồng thời, chúng ta cần xây dựng các hàm của mình một cách cẩn thận để tránh tác dụng phụ. Theo mô hình lập trình chức năng là một cách tuyệt vời để giữ cho mã sạch sẽ, hiệu quả và đơn giản hóa việc kiểm tra

Sử dụng đệ quy thay vì vòng lặp

Để thực thi lặp đi lặp lại một đoạn mã, các lập trình viên hướng đối tượng sử dụng vòng lặp

def recursive_function[n]:

2 hoặc vòng lặp

def recursive_function[n]:

3. Các vòng lặp không tuân thủ kiểu lập trình chức năng vì chúng duy trì một bộ đếm bên ngoài được thay đổi từ bên trong vòng lặp [tác dụng phụ. ]. Trong lập trình chức năng, chúng tôi sử dụng đệ quy để thực thi mã lặp đi lặp lại. Các hàm đệ quy thường được viết theo kiểu sau

def recursive_function[n]:

Ví dụ cổ điển về hàm đệ quy là tính toán số Fibonacci thứ n được thực hiện như vậy

Truyền chức năng làm đối số cho các chức năng khác

Trong OOP truyền thống, bạn có thể truyền đối tượng làm đối số cho hàm. Trong lập trình hàm, bạn có thể chuyển các hàm làm đối số cho các hàm khác. Điều này được gọi là coi các chức năng là công dân hạng nhất, một thuật ngữ bạn có thể thường thấy trong ngành

Hãy xem một ví dụ

Mã này định nghĩa một hàm

def recursive_function[n]:

4 nhân kết quả của một hàm add hoặc hàm trừ [_______12_______6] với ba và trả về giá trị. Hàm

def recursive_function[n]:

4 cũng cho phép truyền bất kỳ hàm nào khác chấp nhận hai tham số và trả về một số nguyên

Lập trình chức năng thúc đẩy khái niệm ngắn gọn khi viết mã. Điều quan trọng là phải ngắn gọn và viết các hàm trong càng ít dòng càng tốt miễn là vẫn duy trì được khả năng đọc. Chúng ta cũng có thể truyền một hàm cho một hàm khác bằng cách viết nó trong đối số bằng lambda

Chúng ta có thể rút ngắn mã trước đó bằng lambda như vậy

Điều này sẽ đưa ra kết quả tương tự như việc thực hiện dài dòng từ trước đó. Lambdas là một công cụ tuyệt vời vì chúng cho phép lập trình viên viết một hàm trong khi vẫn duy trì luồng ý tưởng. Một lập trình viên không còn phải dừng lại, viết một chức năng ở nơi khác và sau đó tiếp tục công việc. Một nhược điểm của lambdas là chúng chỉ phù hợp để thực hiện các chức năng đơn giản;

Phần kết luận

Tóm lại, lập trình hàm là một mô hình mạnh mẽ mang lại nhiều lợi thế. Trong mô hình này, chúng tôi cấu trúc các giải pháp dưới dạng các chức năng. Lập trình hàm khác với lập trình hướng đối tượng. Nó tuân theo kiểu khai báo trái ngược với kiểu mệnh lệnh dẫn đến mã ngắn hơn, dễ kiểm tra hơn, ít bị lỗi hơn và rất phù hợp cho các ứng dụng đa luồng. Nhiều ngôn ngữ cho phép triển khai mô hình lập trình chức năng;

Điều gì tạo nên một ngôn ngữ lập trình chức năng?

Lập trình hàm tìm cách tận dụng hỗ trợ ngôn ngữ trong việc sử dụng hàm làm biến, đối số và giá trị trả về để tạo mã đẹp . Bởi vì các hàm hạng nhất rất linh hoạt và hữu ích, ngay cả các ngôn ngữ OOP mạnh mẽ như Java và C# cũng đã chuyển sang kết hợp hỗ trợ hàm hạng nhất.

Python có chức năng hay thủ tục không?

Python là cả thủ tục và có các tính năng hướng đối tượng, cũng như một số khía cạnh của lập trình chức năng.

Python là ngôn ngữ chức năng hay mệnh lệnh?

Python thường được mã hóa theo cách bắt buộc nhưng có thể sử dụng kiểu khai báo nếu cần. Một số tính năng của Python bị ảnh hưởng bởi Haskell, một ngôn ngữ lập trình chức năng thuần túy.

Ưu điểm của lập trình chức năng trong Python là gì?

Mục đích của các mô hình lập trình khác nhau không phải là biến những thứ trước đây không thể thành có thể, mà là làm cho mọi thứ trở nên dễ dàng mà trước đây khó khăn. Lập trình hàm nhằm mục đích giúp bạn dễ dàng viết các chương trình ngắn gọn, không có lỗi và có thể song song hóa

Chủ Đề