Hướng dẫn how to avoid recursion in python - làm thế nào để tránh đệ quy trong python

Một số ngôn ngữ cung cấp tối ưu hóa cuộc gọi đuôi, số tiền sẽ vứt bỏ khung ngăn xếp trước đó trước khi tạo ngôn ngữ mới. Chỉ có thể khi cuộc gọi đệ quy là thao tác cuối cùng xảy ra (nếu không bạn cần khung ngăn xếp vì nó chỉ vào phần còn lại của các hoạt động). Python không, tuy nhiên.

Bạn có hai tùy chọn:

  1. Nếu chức năng đệ quy nhưng đệ quy không được thực hiện với các cuộc gọi đuôi, thì thường thì việc chuyển đổi sang đệ quy đuôi bằng cách thêm các tham số vào chữ ký chức năng. .
  2. Nếu bạn muốn tránh làm những điều trên, bạn cũng có thể chuyển đổi mã thành kiểu lặp lại sử dụng rõ ràng để lưu trữ mọi thứ, vì kích thước của ngăn xếp của bạn sẽ không bị ràng buộc, trong khi ngăn xếp cuộc gọi thường khá nhỏ (đó là nguyên nhân gây ra giới hạn độ sâu đệ quy).

Lưu ý rằng cả hai điều này là khó khăn hơn khi bạn có, giả sử, ba chức năng gọi nhau là đệ quy. Nhưng ý tưởng tổng thể là đưa ra mã mới bảo tồn hành vi của mã cũ mà không sử dụng đệ quy và rõ ràng cách bạn làm điều đó sẽ khác nhau tùy thuộc vào mã bắt đầu, mặc dù các mẫu chung (được liên kết ở trên) vẫn giữ nguyên .

Trong trường hợp của bạn, mã đi vào một vòng lặp vô hạn hoặc không, tùy thuộc vào a, vì vậy

 a = 1

 def func3():
     while a == 1:
       pass

 func3()

sẽ đủ.

Như một lưu ý phụ: Đối với một số thuật toán, ghi nhớ có thể làm giảm số lượng cuộc gọi. Nếu kết quả cho các đầu vào lớn cho một hàm luôn được tạo ra từ kết quả của các đầu vào nhỏ hơn, được tính toán nhiều lần ("các vấn đề phụ chồng chéo"), thì bạn có thể giữ bộ đệm toàn cầu của các giá trị được trả về và kiểm tra bộ đệm trước khi thực hiện các cuộc gọi mới. Mã ghi nhớ chung có thể được viết bằng Python bằng cách sử dụng các nhà trang trí.

Để tái phát hay không tái diễn, đó là câu hỏi. Chúng ta đều biết về niềm vui chúng ta có với các chức năng đệ quy. Nhưng nó cũng có bộ giảm thiểu riêng, một trong số đó sẽ được giải thích trong bài viết này để giúp bạn chọn một cách khôn ngoan.

Hướng dẫn how to avoid recursion in python - làm thế nào để tránh đệ quy trong python

Giả sử, chúng ta cần tạo một chức năng mà khi được gọi là cần in dữ liệu trong danh sách được liên kết.

Điều này có thể được thực hiện theo 2 cách:

  • 1. với đệ quy
  • 2. Không có đệ quy

1. với đệ quy:With Recursion:

```
def print_linkedlist(head):

   if head is not None:
       print(head.data)
       print_linkedlist(head.next)
```

Cách tiếp cận đầu tiên cũng hoạt động nhưng nếu danh sách thực sự dài như khoảng 1000 yếu tố thì chương trình sẽ đạt độ sâu đệ quy và lỗi. Không quên rằng khi chiều dài danh sách tăng, kích thước ngăn xếp cũng tăng tuyến tính.

Độ sâu đệ quy là gì?

Trước khi chúng tôi đi trước, bạn nên biết rằng vấn đề này là đặc thù của Python. Có những ngôn ngữ mà chúng tôi không gặp phải vấn đề này nhưng điều đó sẽ không được thảo luận ở đây. & nbsp; chúng tôi biết rằng một hàm đệ quy tự gọi. Điều này có nghĩa là một hàm mới được gọi trong hàm gốc. Giả sử một danh sách được liên kết đếm từ 0 đến n bằng 1 bằng cách sử dụng mã đệ quy được đề cập ở trên.

Hàm đầu tiên nhìn vào dữ liệu của nút đầu trong danh sách và sau đó in nó. Nhưng chức năng đầu tiên đã kết thúc. Một hàm cũ không thể kết thúc cho đến khi tất cả các chức năng bên trong nó đã kết thúc. Nếu chúng tôi quan sát ngăn xếp cuộc gọi có danh sách các chức năng đang chạy: & nbsp;

# the first function waiting for
# innermost functions to end
print_linkedlist()

       # the child function called 
       # within the first function
           print_linkedlist()

Ngăn xếp cuộc gọi tiếp tục tăng lên khi các chức năng cũ không bao giờ kết thúc vì chúng đang chờ đợi các chức năng con bên trong kết thúc. Cuối cùng, ngăn xếp cuộc gọi trông giống như:

# original Function
print_linkedlist()

  # first level function
  print_linkedlist()
  
    # second level function
    print_linkedlist()
    
      # third level function
      print_linkedlist()
        ……
          ……
            ……
            
              # 1000 level function – Maximum 
              # Recursion Depth Reached
              print_linkedlist()

Và BAMMM !!!!! Độ sâu đệ quy tối đa !!BAMMM!!!!! MAXIMUM RECURSION DEPTH!!

Hướng dẫn how to avoid recursion in python - làm thế nào để tránh đệ quy trong python

Một độ sâu đệ quy tính số lượng các lớp hoạt động bên trong hàm đệ quy. Trong Python, giới hạn độ sâu đệ quy tối đa mặc định là 1000. Giới hạn giúp ngăn chặn tràn ngăn xếp do đệ quy vô hạn.recursive depth limit is 1000. The limit helps prevent stack overflow which is caused by infinite recursion.

Hướng dẫn how to avoid recursion in python - làm thế nào để tránh đệ quy trong python

Do đó, cách tiếp cận thứ hai như dưới đây tốt hơn vì kích thước ngăn xếp không đổi.

2. & nbsp; không có đệ quy/ lặp lại:

```
def print_linkedlist(node):
   while node:
       print(node.data)
       node=node.next
```

Sự kết luận

Đệ quy là niềm vui khi sử dụng nhưng bạn nên hiểu khi nào và khi nào không sử dụng nó. Một số ngôn ngữ như Scala và Haskell hỗ trợ một tính năng thú vị được gọi là đệ quy cuộc gọi đuôi, điều này ngăn chặn vấn đề độ sâu đệ quy bằng cách kết thúc cuộc gọi chức năng trước đó khi một cuộc gọi mới được thực hiện. Nhưng Python không hỗ trợ tính năng này. Vì vậy, ít nhất là trong Python, thích cách tiếp cận lặp hơn nếu bạn nghĩ rằng chức năng có thể đạt đến giới hạn đệ quy.TAIL CALL RECURSION which prevents the problem of recursion depth by ending the previous function’s call when a new call is made. But Python doesn’t support this feature. So, at least in Python, prefer the iterative approach if you think the function may hit the recursion limit.

Làm thế nào để bạn ngừng đệ quy trong Python?

Khi bạn tìm thấy giải pháp chỉ cần trả lại và sử dụng sys.exit (0) ngay trong dòng tiếp theo, nó sẽ dừng các cuộc gọi đệ quy thêm và đưa bạn ra ngay lập tức.sys. exit(0) right in next line, it would stop further recursive calls and gets you out immediately.

Bạn có nên tránh đệ quy trong Python?

Tuy nhiên, trong hầu hết các trường hợp, các chức năng đệ quy có độ phức tạp rất cao mà chúng ta nên tránh sử dụng.Một trong những giải pháp tốt hơn nhiều là sử dụng kế hoạch động khi có thể, đây có lẽ là cách tốt nhất để giải quyết một vấn đề có thể được chia thành các vấn đề phụ.recursive functions have very high complexity that we should avoid using. One of the much better solutions is to use Dynamic Planning when possible, which is probably the best way to solve a problem that can be divided into sub-problems.

Làm thế nào chúng ta có thể ngăn chặn đệ quy?

Để ngăn chặn đệ quy vô hạn, bạn có thể sử dụng nếu ... câu lệnh khác (hoặc cách tiếp cận tương tự) trong đó một nhánh thực hiện cuộc gọi đệ quy và cái kia thì không.Vì vậy, nó thường trông như thế này.hàm recurse () {if (điều kiện) {recurse ();} other {// ngừng gọi recurse ()}} recurse ();use if...else statement (or similar approach) where one branch makes the recursive call, and the other doesn't. So, it generally looks like this. function recurse() { if(condition) { recurse(); } else { // stop calling recurse() } } recurse();

Làm thế nào để bạn ngăn chặn đệ quy vô hạn trong Python?

Để ngăn chặn đệ quy vô hạn, bạn cần ít nhất một nhánh (tức là câu lệnh IF/ELSE) không thực hiện cuộc gọi đệ quy.Các chi nhánh không có cuộc gọi đệ quy được gọi là trường hợp cơ sở;Các nhánh với các cuộc gọi đệ quy được gọi là các trường hợp đệ quy.Các chức năng cũng có thể được đệ quy lẫn nhau.you need at least one branch (i.e. of an if/else statement) that does not make a recursive call. Branches without recursive calls are called base cases; branches with recursive calls are called recursive cases. Functions can also be mutually recursive.