Ghi nhớ con trăn trang trí
Để lưu trữ một hàm không liên kết đơn giản, chỉ cần đưa thẻ @memorise() vào định nghĩa hàm (cần có dấu ngoặc đơn vì trình trang trí cần được khởi tạo tại thời điểm liên kết để xử lý các đối số cụ thể của ghi nhớ) Show from memorised.decorators import memorise @memorise() def myfunction(): return 'hello world' Bạn có thể làm tương tự đối với các phương thức lớp và thể hiện đơn giản, tuy nhiên đối với hầu hết các phương thức thể hiện, e. g. khi lưu kết quả vào bộ nhớ đệm cho các mô hình cơ sở dữ liệu, bạn có thể muốn bao gồm một số dạng nhận dạng để chọn ra một lệnh gọi phương thức trên một phiên bản từ một phiên bản khác. Bạn có thể làm điều này bằng cách cung cấp danh sách một hoặc nhiều khóa cha khác, đây là tên của các thuộc tính trong phiên bản cha mà bạn muốn được thêm vào khóa memcache Đệ quy cung cấp cho các lập trình viên một cách thuận tiện để chia các vấn đề lớn hơn thành các phần có thể quản lý được. Xem xét các giải pháp lặp và đệ quy cho một tổng số fibonacci # iterative Các giải pháp đệ quy thường dễ đọc và dễ viết hơn cho các vấn đề phân nhánh. Duyệt cây, duyệt đồ thị và chuỗi toán học (thường) được xử lý trực quan hơn bằng cách sử dụng đệ quy Mặc dù nó mang lại sự thuận tiện, chi phí thời gian tính toán của đệ quy đối với các vấn đề phân nhánh tăng theo cấp số nhân với các giá trị lớn hơn của n Hãy xem ngăn xếp cuộc gọi cho fib(6) Chúng tôi thực hiện gần gấp đôi số thao tác ở mỗi cấp độ kế tiếp của cây. Cho chúng ta độ phức tạp thời gian O(2^n) Nếu chúng ta nhìn kỹ hơn vào cái cây của mình, bạn sẽ nhận thấy rằng chúng ta đang lặp lại công việc. fib(2) được tính năm lần, fib(3) được tính ba lần, v.v. Mặc dù đây không phải là vấn đề đối với các giá trị nhỏ của n, hãy tưởng tượng khối lượng công việc lặp đi lặp lại khi tính toán fib(1000). Khi chúng tôi sửa lại giải pháp đệ quy của mình, hãy thử chạy cùng một vấn đề (giả sử là 20) cho cả hai phiên bản và nhận thấy sự khác biệt đáng chú ý trong thời gian hoàn thành Chắc chắn có một cách tốt để ngăn chặn công việc lặp lại và giữ giải pháp tao nhã của chúng tôi? ghi nhớ. Bạn có thể có Bánh của bạn và Ăn nó nữaVới tính năng ghi nhớ, chúng ta có thể “ghi nhớ” (nhớ, lưu trữ) kết quả của các bài toán mà chúng ta đã xử lý trước đó và trả về kết quả được lưu trữ thay vì tính toán lặp lại Ví dụ: một khi fib(2) được tính toán, chúng ta có thể lưu trữ kết quả và sử dụng kết quả đó trong bốn lần gặp fib(2) tiếp theo Điều này làm giảm thời gian chạy của chúng ta từ O(2^n) xuống O(n) vì chúng ta chỉ tính toán từng sợi (0)… sợi (n) một lần Một cách để thực hiện điều này là sử dụng từ điển __fib_cache = {}def fib_memo(n): Và Voila. Chúng tôi đã ghi nhớ thành công một hàm đệ quy Tuy nhiên, chúng ta có thể tiến xa hơn một bước và ghi nhớ trừu tượng cho bất kỳ hàm đệ quy nào người trang trí. Chức năng sử dụng chức năng để thực hiện chức năng khácDecorators được gọi là “Higher order functions”. các hàm lấy các hàm khác làm tham số. Ở đây chúng tôi sẽ sử dụng một trình trang trí để khái quát hóa việc ghi nhớ Đây là một giải pháp trang trí def memoize(func): Hãy chia nhỏ nó xuống từng dòng Trình trang trí của chúng tôi là một hàm nhận một hàm khác làm đối số, chúng tôi khai báo nó như vậy trên dòng 1 Tiếp theo, chúng tôi khai báo một từ điển Chúng tôi sẽ quay lại
__fib_cache = {}def fib_memo(n):0 __fib_cache = {}def fib_memo(n):1 là một từ khóa chỉ ra rằng __fib_cache = {}def fib_memo(n):2 nhận một số đối số tùy ý e. g. __fib_cache = {}def fib_memo(n):3 hoặc __fib_cache = {}def fib_memo(n):4 đều hợp lệ. Tương tự, __fib_cache = {}def fib_memo(n):5 đại diện cho một số lượng đối số từ khóa tùy ý (các tham số được xác định tại lệnh gọi hàm) e. g. __fib_cache = {}def fib_memo(n):6. Ghi chú. Bạn có thể sử dụng các tham số chuyên dụng này trong bất kỳ chức năng nào Dòng sau khai báo một __fib_cache = {}def fib_memo(n):7 cho __fib_cache = {}def fib_memo(n):8 của chúng ta dựa trên các tham số đã cho. Nếu chúng tôi đã thấy sự kết hợp các tham số này trước đây, chúng tôi sẽ lấy kết quả từ __fib_cache = {}def fib_memo(n):8 , nếu không, hãy tạo một khóa mới bằng cách sử dụng func ban đầu như đã được xác định (e. g. sử dụng def memoize(func):1) và gán giá trị của nó cho kết quả e. g. ( lưu trữ kết quả của def memoize(func):2) Dòng cuối cùng bên trong def memoize(func):3 trả về kết quả của một lần gọi tới func với các tham số đã choDòng cuối cùng trả về def memoize(func):3, đại diện cho một phiên bản đã sửa đổi của hàm ban đầu của chúng tôi với các tính năng (được trang trí) bổ sung, nghĩa là lưu trữ kết quả của mỗi lệnh gọi mới Cuối cùng, chúng tôi đánh dấu chức năng ban đầu của mình bằng def memoize(func):6. Ký hiệu '@' yêu cầu trình biên dịch chuyển hàm ngay bên dưới nó thành một hàm bậc cao hơn có tên là __fib_cache = {}def fib_memo(n):0 — trong trường hợp của chúng tôi, hàm này trả về một phiên bản được ghi nhớ của def memoize(func):8. Phiên bản này của hàm sẽ ngay lập tức trả về kết quả mà chúng ta đã tính toán trước đó, nếu không, nó sẽ gọi hàm def memoize(func):9 ban đầu để xác định số đó sẽ là bao nhiêu@functools là gì. kết thúc tốt đẹp?
def memoize(func):1. Đối với mục đích gỡ lỗi, thật hữu ích khi có quyền truy cập vào tên và chuỗi tài liệu của chức năng ban đầu được gọi, không phải chức năng trang trí, vì cùng một công cụ trang trí có thể được áp dụng cho vô số chức năngHãy tự mình thử Lần tới khi bạn gặp một hàm đệ quy, hãy nghĩ xem liệu bạn có thể cải thiện hiệu suất của nó bằng tính năng ghi nhớ hay không, sau đó trừu tượng hóa tính năng ghi nhớ đó cho các hàm khác bằng cách thêm một trình trang trí Ghi nhớ trong Python là gì?Ghi nhớ là kỹ thuật tối ưu hóa phần mềm hiệu quả được sử dụng để tăng tốc chương trình . Nó cho phép bạn tối ưu hóa chức năng python bằng cách bắt đầu ra của nó dựa trên các tham số đầu vào được cung cấp. Ghi nhớ đảm bảo rằng một phương thức chỉ chạy cho cùng một đầu vào một lần.
Sự khác biệt giữa ghi nhớ và ghi nhớ là gì?Ghi nhớ là một kỹ thuật tối ưu hóa được sử dụng chủ yếu để tăng tốc các chương trình máy tính bằng cách lưu trữ kết quả của các lệnh gọi hàm đắt tiền và trả về kết quả được lưu trong bộ nhớ cache khi các đầu vào tương tự xảy ra lần nữa. Ghi nhớ hiểu một cách đơn giản là ghi nhớ hoặc lưu trữ trong bộ nhớ .
Ghi nhớ trong lập trình động là gì?Ghi nhớ là một kỹ thuật để cải thiện hiệu suất của các thuật toán đệ quy . Nó liên quan đến việc viết lại thuật toán đệ quy để câu trả lời cho các vấn đề được tìm thấy, chúng được lưu trữ trong một mảng. Các cuộc gọi đệ quy có thể tra cứu kết quả trong mảng thay vì phải tính toán lại chúng.
Sự khác biệt giữa phương pháp ghi nhớ và lập bảng là gì?Nhanh vì kết quả của các bài toán con đã giải quyết trước đó có thể được truy cập trực tiếp từ bảng. Nó chậm vì cần phải thực hiện nhiều lệnh gọi đệ quy và trả về. Trong phiên bản lập bảng, tất cả các mục phải được điền từng mục một. Trong phiên bản ghi nhớ, các mục trong bảng được điền theo yêu cầu . |