Hướng dẫn dùng myclass evaluation python

answer

39

Hướng dẫn dùng myclass evaluation python

Thay vào đó, bạn có thể sử dụng một @propertytrên metaclass :

class MyMetaClass(type):
    @property
    def my_data(cls):
        if getattr(cls, '_MY_DATA', None) is None:
            my_data = ...  # costly database call
            cls._MY_DATA = my_data
        return cls._MY_DATA


class MyClass(metaclass=MyMetaClass):
    # ...

Điều này tạo ra my_datamột thuộc tính trên lớp, do đó, cuộc gọi cơ sở dữ liệu đắt tiền bị hoãn lại cho đến khi bạn cố gắng truy cập MyClass.my_data. Kết quả của lệnh gọi cơ sở dữ liệu được lưu vào bộ nhớ đệm bằng cách lưu trữ nó trong MyClass._MY_DATA, lệnh gọi chỉ được thực hiện một lần cho lớp.

Đối với Python 2, hãy sử dụng class MyClass(object):và thêm một __metaclass__ = MyMetaClassthuộc tính trong nội dung định nghĩa lớp để đính kèm siêu kính.

Bản giới thiệu:

>>> class MyMetaClass(type):
...     @property
...     def my_data(cls):
...         if getattr(cls, '_MY_DATA', None) is None:
...             print("costly database call executing")
...             my_data = 'bar'
...             cls._MY_DATA = my_data
...         return cls._MY_DATA
... 
>>> class MyClass(metaclass=MyMetaClass):
...     pass
... 
>>> MyClass.my_data
costly database call executing
'bar'
>>> MyClass.my_data
'bar'

Điều này hoạt động vì một bộ mô tả dữ liệu giống như propertyđược tra cứu trên kiểu mẹ của một đối tượng; cho các lớp typetypecó thể được mở rộng bằng cách sử dụng kính đo.

39 hữu ích 5 bình luận chia sẻ

answer

11

Hướng dẫn dùng myclass evaluation python

Câu trả lời này chỉ dành cho thuộc tính / phương thức cá thể điển hình , không dành cho thuộc tính lớp / classmethod, hoặc staticmethod.

Đối với Python 3.8+, làm thế nào về việc sử dụng trình cached_propertytrang trí? Nó ghi nhớ.

from functools import cached_property

class MyClass:

    @cached_property
    def my_lazy_attr(self):
        print("Initializing and caching attribute, once per class instance.")
        return 7**7**8

Đối với Python 3.2+, làm thế nào về việc sử dụng cả hai propertylru_cachedecorator? Bản ghi nhớ thứ hai.

from functools import lru_cache

class MyClass:

    @property
    @lru_cache()
    def my_lazy_attr(self):
        print("Initializing and caching attribute, once per class instance.")
        return 7**7**8

Tín dụng: câu trả lời của Maxime R.

11 hữu ích 0 bình luận chia sẻ

answer

6

Hướng dẫn dùng myclass evaluation python

Một cách tiếp cận khác để làm cho mã sạch hơn là viết một hàm trình bao bọc thực hiện logic mong muốn:

def memoize(f):
    def wrapped(*args, **kwargs):
        if hasattr(wrapped, '_cached_val'):
            return wrapped._cached_val
        result = f(*args, **kwargs)
        wrapped._cached_val = result
        return result
    return wrapped

Bạn có thể sử dụng nó như sau:

@memoize
def expensive_function():
    print "Computing expensive function..."
    import time
    time.sleep(1)
    return 400

print expensive_function()
print expensive_function()
print expensive_function()

Kết quả đầu ra:

Computing expensive function...
400
400
400

Bây giờ, classmethod của bạn sẽ trông như sau, ví dụ:

class MyClass(object):
        @classmethod
        @memoize
        def retrieve_data(cls):
            print "Computing data"
            import time
            time.sleep(1) #costly DB call
            my_data = 40
            return my_data

print MyClass.retrieve_data()
print MyClass.retrieve_data()
print MyClass.retrieve_data()

Đầu ra:

Computing data
40
40
40

Lưu ý rằng điều này sẽ chỉ lưu vào bộ nhớ cache một giá trị cho bất kỳ tập hợp đối số nào của hàm, vì vậy nếu bạn muốn tính các giá trị khác nhau tùy thuộc vào giá trị đầu vào, bạn sẽ phải thực hiện memoizephức tạp hơn một chút.

6 hữu ích 0 bình luận chia sẻ

answer

0

Hướng dẫn dùng myclass evaluation python

Hãy xem xét Dickensgói có thể cài đặt bằng pip có sẵn cho Python 3.5+. Nó có một descriptorsgói cung cấp các trình trang trí cachedpropertyvà có liên quan cachedclassproperty, việc sử dụng chúng được hiển thị trong ví dụ bên dưới. Nó dường như hoạt động như mong đợi.

from descriptors import cachedproperty, classproperty, cachedclassproperty

class MyClass:
    FOO = 'A'

    def __init__(self):
        self.bar = 'B'

    @cachedproperty
    def my_cached_instance_attr(self):
        print('Initializing and caching attribute, once per class instance.')
        return self.bar * 2

    @cachedclassproperty
    def my_cached_class_attr(cls):
        print('Initializing and caching attribute, once per class.')
        return cls.FOO * 3

    @classproperty
    def my_class_property(cls):
        print('Calculating attribute without caching.')
        return cls.FOO + 'C'

0 hữu ích 0 bình luận chia sẻ

answer

0

Hướng dẫn dùng myclass evaluation python

Ringcung cấp lru_cachegiao diện giống nhưng hoạt động với bất kỳ loại mô tả nào hỗ trợ: https://ring-cache.readthedocs.io/en/latest/quickstart.html#method-classmethod-staticmethod

class Page(object):
    (...)

    @ring.lru()
    @classmethod
    def class_content(cls):
        return cls.base_content

    @ring.lru()
    @staticmethod
    def example_dot_com():
        return requests.get('http://example.com').content

Xem các liên kết để biết thêm chi tiết.

0 hữu ích 0 bình luận chia sẻ