Có một cách chuẩn để lưu trữ các phương thức cá thể trong python không?


9

Tôi có một số chức năng chuyên sâu tính toán trong tập lệnh python của tôi mà tôi muốn lưu trữ. Tôi đã tìm kiếm các giải pháp trên stack stack và tìm thấy rất nhiều liên kết:

  1. /programming/4431703/python-resitable-instance-method-memoization-decorator
  2. https://wiki.python.org/moin/PythonDecoratorL Library#Memoize
  3. http://pythonhosted.org/cachetools/
  4. https://pythonhosted.org/Flask-Cache/ (Tôi đã sử dụng ứng dụng này cho các ứng dụng bình, nhưng ứng dụng này không phải là ứng dụng bình).

Cuối cùng, tôi đã kết thúc việc dán nó vào chương trình của tôi. Có vẻ như đủ đơn giản - và hoạt động tốt.

class memoized(object):
    '''Decorator. Caches a function's return value each time it is called.
    If called later with the same arguments, the cached value is returned
    (not reevaluated).
    '''
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, *args):
        if not isinstance(args, collections.Hashable):
            return self.func(*args)
        if args in self.cache:
            return self.cache[args]
        else:
            value = self.func(*args)
            self.cache[args] = value
            return value

    def __repr__(self):
        '''Return the function's docstring.'''
        return self.func.__doc__

    def __get__(self, obj, objtype):
        '''Support instance methods.'''
        return functools.partial(self.__call__, obj)

Tuy nhiên, tôi tự hỏi liệu có một thực hành tốt nhất trong Python. Tôi đoán tôi đã giả định rằng sẽ có một gói được sử dụng rất phổ biến để xử lý việc này và bối rối về lý do tại sao điều này không tồn tại. http://pythonhosted.org/cachetools/ chỉ có trên phiên bản .6 và cú pháp phức tạp hơn việc thêm một trình trang trí @memoize, như trong các giải pháp khác.

Câu trả lời:


12

Không có cách Pythonic kinh điển, duy nhất để làm điều này. Không ai trong số chúng tôi biết, ở bất cứ giá nào - và tôi đang nói như một người đã xem, và là tác giả của gói ghi nhớ thành công .

Tuy nhiên, tôi tin rằng việc bạn không tìm thấy nghệ thuật trước đây có thể là một vấn đề thuật ngữ nhiều như bất cứ điều gì. Bạn yêu cầu lưu trữ . Đó là một thuật ngữ thích hợp, nhưng nó quá rộng. Bộ nhớ đệm kết quả của một cuộc gọi chức năng hoặc hoạt động cụ thể để sử dụng sau này được gọi cụ thể hơn là ghi nhớ hoặc ghi nhớ . Và thực sự có rất nhiều gói ghi nhớ có sẵn từ cộng đồng , cũng như nhiều công thức nấu ăn ( ví dụ: gói này ). Tôi cũng đã thấy các chức năng ghi nhớ trong nhiều gói tiện ích đa mục đích. Nhiều người trong số họ đã trưởng thành, chịu trận và không ngừng sử dụng trong sản xuất - không chỉ là "mã phiên bản 0.6".

Tại sao việc ghi nhớ không được xử lý theo quy tắc hoặc thành ngữ hơn tôi không thể nói. Có lẽ bởi vì có nhiều cách khác nhau để thực hiện nó với những đức tính và sự đánh đổi khác nhau. Hoặc có lẽ bởi vì đã có rất nhiều cách tiếp cận khác nhau được sử dụng. Tôi thường tìm thấy các tính năng - "làm phẳng danh sách danh sách" là một tính năng khác - rằng các cộng đồng ngôn ngữ khác háo hức hội tụ nhưng cộng đồng Python hoặc các quyền lực dường như thích xử lý như các công thức nấu ăn hơn là cam kết với một API cụ thể. Trong mọi trường hợp, nếu mã của bạn hoạt động, chào mừng bạn đến với hàng ngũ những người ghi nhớ thành công!

Cập nhật

Vì thư viện chuẩn Python 3 (cho phiên bản 3.2 trở lên) bao gồm một trình lru_cachetrang trí ( tài liệu ở đây ), tôi phải nói rằng nó trông giống như một nỗ lực cuối cùng để chuẩn hóa trường hợp sử dụng ghi nhớ phổ biến nhất. Rằng sự phát triển quá muộn của Python có lẽ là lý do tại sao không có giải pháp chung, nhưng đối với mã mới, nó gần với kinh điển như bạn sẽ tìm thấy.


1
Python 3.8 đã thêm trình @cached_propertytrang trí , phù hợp hơn cho các phương thức có giá trị trả về được dự kiến ​​sẽ giữ nguyên trong suốt vòng đời của thể hiện.
Patrick Brinich-Langlois

0

Vì một phương thức cá thể được phép sử dụng các thuộc tính tự và đặc biệt sửa đổi chúng, bạn không thể đảm bảo tính chính xác của phương thức cá thể ghi nhớ tùy ý. Ngoài ra, việc triển khai của bạn thêm một ràng buộc ngầm định vào đối tượng của bạn để có thể băm và nhấn bộ nhớ cache tùy thuộc vào hàm băm đó, bạn bị giới hạn ở các lớp bạn có thể sử dụng và các trường bạn có thể thêm vào các lớp có phương thức ghi nhớ (hoặc kế thừa một).

Vì những lý do này, nếu bạn cần ghi nhớ một hàm, thiết kế tốt hơn là biến phương thức cá thể đắt tiền thành phương thức tĩnh, rõ ràng chuyển đến nó các thuộc tính đối tượng cần thiết làm đối số. Điều này giải phóng bàn tay của bạn về thiết kế lớp và có thể cải thiện bộ nhớ cache. Điều này cũng giúp đơn giản hóa và khái quát hóa mã ghi nhớ. Việc triển khai hạt mịn tồn tại cho mong muốn này, đôi khi cho phép bạn tùy chỉnh kích thước bộ đệm, phương thức thời lượng / không hợp lệ, đảm bảo an toàn luồng, độ bền ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.