Kiểu dữ liệu Function trong Python - Đệ quy (recursion)

Lập trình Python cơ bản

5.0 (5 đánh giá)
Tạo bởi Kteam Cập nhật lần cuối 23:43 29-11-2021 51.796 lượt xem 7 bình luận
Học nhanh

Danh sách bài học

Kiểu dữ liệu Function trong Python - Đệ quy (recursion)

Dẫn nhập

Trong bài trước, Kteam đã giới thiệu đến bạn KIỂU DỮ LIỆU FUNCTION TRONG PYTHON – FUNCTIONAL TOOLS.

Và ở bài này Kteam sẽ lại tìm hiểu với các KIỂU DỮ LIỆU FUNCTION – ĐỆ QUY trong Python.


Nội dung

Để đọc hiểu bài này tốt nhất bạn cần:

Bạn và Kteam sẽ cùng tìm hiểu những nội dung sau đây

  • Giới thiệu về đệ quy
  • Minh họa đệ quy  bằng cách tính tổng
  • Đệ quy theo phong cách Python
  • Đệ quy và vòng lặp

Giới thiệu về đệ quy

Đệ quy là một mảng kiến thức nâng cao, ở Python thì nó không thường xuyên được dùng đến, do cách xử lí của Python có thể sử dụng những cấu  trúc vòng lặp đơn giản mà không cần dùng tới đệ quy. Nhưng dù sao thì đây cũng là  một kĩ thuật khá hữu dụng mà bạn đọc nên biết. Nó cũng chỉ đơn giản là việc chính nó gọi nó.

Lấy một ví dụ cụ thể: Giả sử ta có một list gồm n phần tử, nhiệm vụ của chúng ta là lấy toàn bộ các phần tử của list đó.

Để giải bài toán này, ta có thể sử dụng một hàm put: giúp lấy ra một phần tử trong list, đồng thời kiếm tra xem list có rỗng hay không. Nếu list đó vẫn còn phần tử, thì ta lại gọi hàm put thêm một lần nữa (để tiếp tục lấy và kiểm tra). Làm như thế cho đến khi list đó rỗng.

Bản thân việc gọi một hàm trong chinh nó được gọi là đệ quy. Trong trường hợp trên, đệ quy là việc khi ta đang chạy hàm put mà lại gọi hàm đó tiếp (trường hợp list có nhiều phần tử).


Minh họa đệ quy bằng cách tính tổng

Ta sẽ tính tổng các phần tử của một list (hoặc một sequence nào đó) bằng cách dùng đệ quy (Ví dụ này chỉ là minh họa, thực tế khi làm bạn nên sử dụng hàm sum)

>>> def cal_sum(lst):
...     if not lst: # tương đương if len(lst) == 0:
...             return 0
...     else:
...             return lst[0] + cal_sum(lst[1:])
...
>>> cal_sum([1, 2, 3, 4])
10
>>> cal_sum([1, 2, 3, 4, 5])
15

Ở ví dụ trên, ta liên tục gọi lại hàm cal_sum với argument là phần còn lại của List tính từ index 1. Ở mỗi lần gọi hàm, ta để lại giá trị index 0 List để khi trong List không còn phần tử nào ta sẽ trả về số 0 để kết thúc đệ quy.

Nếu bạn thấy vẫn còn chưa hiểu rõ thì cũng đừng lo lắng, ai cũng đều cảm thấy khó hiểu và điều này thường xuyên xảy ra với những bạn mới học. Những lúc như thế này, bạn nên để thêm một cái hàm print để xem cụ thể là chuyện gì xảy ra

>>> def cal_sum(lst):
...     print(lst)
...     if not lst:
...             return 0
...     else:
...             return lst[0] + cal_sum(lst[1:])
...
>>> cal_sum([1, 2, 3, 4])
[1, 2, 3, 4]
[2, 3, 4]
[3, 4]
[4]
[]
10

Nếu bạn vẫn còn khó hiểu hãy vẽ ra giấy. Đây là cách mà mình đã làm

Kiểu dữ liệu Function trong Python - Đệ quy (recursion)


Đệ quy theo phong cách Python

Bạn còn nhớ cú pháp if/else trong lambda không? Nó còn có tên khác là ternary expression. Bạn có thể áp dụng để sử dụng nó để đệ quy:

>>> def cal_sum(lst):
...     return 0 if not lst else lst[0] + cal_sum(lst[1:])
...
>>> cal_sum([1, 2, 3])
6

Giả sử một list có n phần tử thì với đệ quy như trên cần phải có n + 1 lần return, ta có thể giảm bớt xuống còn n lần return bằng cách:

>>> def cal_sum(lst):
...     return lst[0] if len(lst) == 1 else lst[0] + cal_sum(lst[1:])
...
>>> cal_sum([1, 2, 3])
6

Lưu ý: cách này không sử dụng được trong trường hợp container rỗng

Hoặc ta có thể sử dụng packing argument:

>>> def cal_sum(lst):
...     idx0, *r = lst # idx0, r = lst[0], lst[1:]
...     return idx0 if not r else idx0 + cal_sum(r)
...
>>> cal_sum([1, 2, 3])
6

Lưu ý: cách này cũng không sử dụng được khi container là rỗng. Tuy nhiên điểm lợi của nó cũng như cách vừa nãy là ta có thể cộng không chỉ số mà là chuỗi, hoặc list

>>> cal_sum(['a', 'b', 'c'])
'abc'
>>> cal_sum([[1, 2], [3, 4], [5, 6]])
[1, 2, 3, 4, 5, 6]

Đệ quy cũng có thể chuyển hướng. Hãy xem ví dụ sau. Một hàm gọi một hàm khác, sau đó lại gọi lại hàm đã gọi nó.

>>> def cal_sum(lst):
...     if not lst: return 0
...     return call_cal_sum(lst)
...
>>> def call_cal_sum(lst):
...     return lst[0] + cal_sum(lst[1:])
...
>>> cal_sum([1, 2, 3, 4, 5])
15

Đệ quy và vòng lặp

Ở những ví dụ trước, nếu phải chọn vòng lặp hay là đệ quy để xử lí thì Kteam khuyên bạn đọc nên chọn vòng lặp. Python chú trọng việc làm đơn giản hóa mọi việc như là vòng lặp vì nó theo một cách bình thường đơn giản. Vòng lặp cũng không yêu cầu bạn phải tạo ra một hàm mới có thể sử dụng được. Và thêm nữa, đệ quy còn thua vòng lặp ở mặt hiệu quả về bộ nhớ và thời gian thực hiện.


Kết luận

Qua bài viết này, bạn đã biết thêm về đệ quy. Ngoài ra, bạn cũng đã nắm được kha khá các kiến thức cơ bản của Python thông qua khóa LẬP TRÌNH PYTHON CƠ BẢN. Hy vọng khóa học sẽ là nền tảng tốt để bạn có thể tiếp tục tự nghiên cứu hoặc tiến tới các khóa học Python khác.

Cảm ơn bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quyên “Luyện tập – Thử thách – Không ngại khó”.


Tải xuống

Tài liệu

Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Kiểu dữ liệu Function trong Python - Đệ quy (recursion) dưới dạng file PDF trong link bên dưới.

Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com

Đừng quên likeshare để ủng hộ Kteam và tác giả nhé!


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Quan tâm lập trình và lịch sử.

Thích tìm hiểu công nghệ mới



Khóa học

Lập trình Python cơ bản

Lập trình Python cơ bản

Đánh giá

linhhng đã đánh giá 09:33 26-07-2022

hay

roynguyen đã đánh giá 21:15 28-08-2021

longlaptrinh đã đánh giá 21:06 23-04-2021

vinhzcc123 đã đánh giá 23:05 23-02-2020

Cảm ơn anh

Le Van Son đã đánh giá 20:53 28-03-2019

còn class nữa a ơi

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Đặng Duy Anh đã bình luận 16:05 19-02-2021

>>> def cal_sum(lst):
...     idx0, *r = lst # idx0, r = lst[0], lst[1:]
...     return idx0 if not r else idx0 + cal_sum(r)
...
>>> cal_sum([1, 2, 3])
6
 em không hiểu phần *r, tại sao lại thế này  idx0, r = lst[0], lst[1:] ad ới

 

meolonvameocon đã bình luận 21:33 11-02-2019

Làm tiếp phần class đi anh.

Quy Pham đã bình luận 10:41 07-09-2018

ad oi, không có phần thủ tục hả ad

Không có video.