Có thể đệ quy đuôi trong Python không?
Tôi đang xem qua ghi chú xuất sắc của Kyle Miller. “Đệ quy cuộc gọi đuôi trong Python” và quyết định thử nghiệm các biến thể của kỹ thuật Show Ý tưởng là. người ta có thể muốn loại bỏ việc sử dụng ngăn xếp lệnh gọi ngôn ngữ maximum recursion depth exceeded in comparison3 trong trường hợp "gọi đuôi" (một lệnh gọi hàm mà kết quả không được sử dụng bởi hàm gọi mà thay vào đó được trả về ngay lập tức). Loại bỏ cuộc gọi đuôi có thể vừa tăng tốc chương trình vừa cắt giảm chi phí duy trì khung ngăn xếp trung gian và môi trường sẽ không bao giờ được sử dụng lại Ghi chú chỉ ra một cách chính xác rằng maximum recursion depth exceeded in comparison3 cố tình không có câu lệnh maximum recursion depth exceeded in comparison5, một công cụ mà người ta có thể sử dụng để thực hiện loại bỏ cuộc gọi đuôi thực. Vì vậy, Kyle Miller đã xây dựng một sự thay thế dựa trên cấu trúc dữ liệu cho ngăn xếp cuộc gọi, cho phép một người làm việc xung quanh giới hạn ngăn xếp cho một chức năng cụ thể (không thay đổi bất kỳ cấu hình maximum recursion depth exceeded in comparison3 nào và không thay đổi hành vi của các chức năng khác) Tất nhiên, maximum recursion depth exceeded in comparison3 có một số điều khiển luồng điều khiển kỳ lạ. maximum recursion depth exceeded in comparison1 và maximum recursion depth exceeded in comparison2. Vì vậy, tôi quyết định xây dựng một giải pháp dựa trên maximum recursion depth exceeded in comparison3 của riêng chúng tôi bằng cách sử dụng maximum recursion depth exceeded in comparison1 Vui lòng đọc tiếp để biết cách chúng tôi thực hiện việc này và một số ví dụ Hãy xem một ví dụ về vấn đề. Lưu ý chức năng tự gọi (ngớ ngẩn) không thành công vì nó chạy hết ngăn xếp cuộc gọi trước khi hoàn thành phép tính của nó Trong 1] def recursive_example(n, d=1): if n <= 1: return d else: return recursive_example(n - 1, d + 1) try: recursive_example(10000) except Exception as ex: print(ex) maximum recursion depth exceeded in comparison Tất nhiên, nắm bắt gọn gàng đệ quy thừa (như maximum recursion depth exceeded in comparison3 đã làm ở trên) là một tính năng. Đó là một cách để ngăn chặn các lần truy cập chạy trốn có thể xảy ra Tuy nhiên, nếu chúng ta muốn một chức năng cụ thể vượt quá giới hạn này (đặc biệt là đối với các cuộc gọi đuôi, không yêu cầu chi phí bộ nhớ. ). chúng ta cần thiết lập một khung tương tự như “Đệ quy cuộc gọi đuôi trong Python” Trước tiên, chúng tôi xây dựng một "thunk" để biểu thị việc đánh giá một hàm với tất cả các đối số được chỉ định, nhưng điều đó vẫn chưa xảy ra. Chúng tôi triển khai các tính toán đang chờ xử lý với lớp maximum recursion depth exceeded in comparison6 (nguồn tại đây). Thêm một chút là. chúng tôi có maximum recursion depth exceeded in comparison7 mở rộng maximum recursion depth exceeded in comparison8, vì vậy chúng tôi có thể sử dụng maximum recursion depth exceeded in comparison1 để nhảy ra khỏi bối cảnh chức năng hiện tại của chúng tôi Sau đó, khi chúng tôi có những gì thường là "cuộc gọi đuôi" có dạng " maximum recursion depth exceeded in comparison00", thay vào đó chúng tôi viết " maximum recursion depth exceeded in comparison01". Ý tưởng là. chúng tôi kết thúc chức năng hiện tại của mình bằng cách tăng ngoại lệ và chính ngoại lệ đó có hướng dẫn cho bước tiếp theo mong muốn hoặc tiếp tục tính toán. Sau đó, một trình bao bọc bên ngoài sẽ đánh giá lặp đi lặp lại bất kỳ maximum recursion depth exceeded in comparison7 nào gặp phải. Do đó, bất kỳ đệ quy đuôi nào cũng được thay thế bằng phép lặp và chúng tôi đã loại bỏ việc sử dụng ngăn xếp và bộ nhớ của các lệnh gọi đuôi. Cũng có thể sử dụng ký hiệu kiểu maximum recursion depth exceeded in comparison03 với trình bao bọc maximum recursion depth exceeded in comparison7, nhưng chúng tôi cảm thấy ký hiệu maximum recursion depth exceeded in comparison1 ghi lại ý định rõ ràng hơn Một ví dụ được đưa ra ở đây Trong 2] maximum recursion depth exceeded in comparison0 Ra[2] maximum recursion depth exceeded in comparison7 thông báo. maximum recursion depth exceeded in comparison1 sẽ ném qua bất kỳ chức năng trung gian nào, do đó, bất kỳ cuộc gọi không theo đuôi nào (trực tiếp hoặc gián tiếp) đến các chức năng ném này sẽ phải sử dụng bộ bảo vệ maximum recursion depth exceeded in comparison07. Sau khi làm việc với một số ví dụ, chúng tôi đã giải quyết rằng cơ chế dựa trên lợi nhuận ban đầu tốt hơn. Các ngoại lệ quá khó quản lý và không thêm nhiều. Để điều chỉnh ví dụ dựa trên lợi nhuận của chúng tôi, vui lòng xem tại đây Chúng tôi cũng có thể chuyên biệt hóa phương thức cho các cuộc gọi phương thức như chúng tôi trình bày bên dưới. Mẫu chúng tôi đang sử dụng là một mẫu đơn giản. các phương thức kết thúc bằng gạch dưới đưa ra các ngoại lệ thay cho các cuộc gọi đuôi (và chỉ gọi các phiên bản của phương thức gạch dưới) và một phương thức bên ngoài không có gạch dưới thực hiện xử lý ngoại lệ Trong 3] maximum recursion depth exceeded in comparison0 Ra[3] maximum recursion depth exceeded in comparison7 Và bạn có nó rồi đấy. loại bỏ cuộc gọi đuôi dựa trên ngoại lệ không gian thấp. Đây là một trong những ý tưởng mà chúng tôi đang xem xét sử dụng để loại bỏ giới hạn duyệt đối tượng được lồng sâu khỏi phiên bản maximum recursion depth exceeded in comparison3 sắp tới của maximum recursion depth exceeded in comparison09 (phiên bản còn lại là trình lặp truy cập cây không đệ quy) Tại sao Python không hỗ trợ đệ quy đuôi?Lý do của giới hạn này là (trong số những lý do khác) việc thực hiện các cuộc gọi đệ quy cần rất nhiều bộ nhớ và tài nguyên vì mỗi khung trong ngăn xếp cuộc gọi phải được duy trì cho đến khi cuộc gọi hoàn tất . .
Đệ quy đuôi có nhanh hơn trong Python không?Nó sử dụng ít bộ nhớ hơn so với hàm đệ quy không đuôi. Nhanh hơn vì trình biên dịch có thể thực hiện tối ưu hóa đặc biệt cho các lệnh gọi hàm đệ quy đuôi .
Ngôn ngữ nào hỗ trợ đệ quy đuôi?Loại bỏ đệ quy đuôi là một tính năng rất thú vị có sẵn trong các ngôn ngữ Lập trình hàm, như Haskell và Scala . Nó thực hiện các cuộc gọi hàm đệ quy nhanh như vòng lặp.
Là đệ quy đuôi luôn luôn có thể?Không phải hàm đệ quy nào cũng có thể biến thành hàm đệ quy đuôi . Cụ thể, nếu một hàm thực hiện lời gọi đệ quy, nhưng sau đó kiểm tra kết quả và thực hiện những việc khác nhau tùy thuộc vào giá trị của nó, thì có thể không thực hiện được hàm đệ quy đuôi. |