項目中遇到的裝飾器

1. functools.partial

django 用法:python

  • 代碼出現的地方django

    path = partial(_path, Pattern=RoutePattern)
    re_path = partial(_path, Pattern=RegexPattern)
  • 詳解緩存

    # 調用path時至關於調用_path('login/', LoginView.as_view(), Pattern=RoutePattern)
    urlpatterns = [
        path('login/', LoginView.as_view()),
    ]

2. functools.lru_cache

django:app

  • manage.py 命令行執行時fetch_command函數調用get_commands函數

  • get_commands每次調用都會返回一個dict,當settings文件沒有改變的時,返回的值是不變的,使用裝飾器則減小了每次啓動服務計算commands的時間fetch

    @functools.lru_cache(maxsize=None)
    def get_commands():
        commands = {name: 'django.core' for name in find_commands(__path__[0])}
    
        if not settings.configured:
            return commands
    
        for app_config in reversed(list(apps.get_app_configs())):
            path = os.path.join(app_config.path, 'management')
            commands.update({name: app_config.name for name in find_commands(path)})
    
        return commands
  • functools.lru_cache(maxsize=128, typed=False)this

    -- maxsize表明緩存的內存佔用值,超過這個值以後,以前的結果就會被釋放,而後將新的計算結果進行緩存,其值應當設爲2的冪
    -- typed若爲True,則會把不一樣的參數類型獲得的結果分開保存
  • 做用:主要是用來作臨時緩存,把耗時的操做結果暫時保存,避免重複計算,好比生成斐波那契數列時,函數後覺得結果依賴前兩位計算結果值url

3. classonlymethod 和 classmethod

  • django CBV 中 類繼承View類,urlpattern裏面調用as_view實現一個接口不一樣不一樣調用方式走不一樣的邏輯,as_view方法使用@classonlymethod裝飾器
  • 源碼
    class classonlymethod(classmethod):
         def __get__(self, instance, cls=None):
             if instance is not None:
                 raise AttributeError("This method is available only on the class, not on instances.")
             return super().__get__(instance, cls)
  • 源碼能夠看出classonlymethod和classmethod的區別即爲,classonlymethod只能由類調用,實例對象調用時會拋出對象異常

4. @functools.wraps(func) 用於定義裝飾器的時候,特別是多個函數被裝飾器裝飾時,保留原函數的名稱和屬性

  • 使用示例:
    def my_decorator(func):      
         @functools.wraps(func)
         def wrapper(*args, **kwargs):
             '''do something'''
             return func(*args, **kwargs)
         return wrapper
  • 源碼,根據源碼能夠看出wraps 函數實現了更新包裝器函數,將被包裝的函數屬性賦給新的包裝器函數並返回,因此說該函數的做用是保留被裝飾對象的屬性
    # 使用偏函數,對傳進來的包裝器函數調用update_wrapper
     # 返回一個裝飾器,該裝飾器使用裝飾後的函數做爲包裝器參數並調用wraps()的參數做爲其他參數來調用update_wrapper()。 
     # 默認參數與update_wrapper()相同。
     def wraps(wrapped,
               assigned = WRAPPER_ASSIGNMENTS,
               updated = WRAPPER_UPDATES):
         """Decorator factory to apply update_wrapper() to a wrapper function
            Returns a decorator that invokes update_wrapper() with the decorated function as the wrapper argument and the arguments to wraps() as the remaining arguments. Default arguments are as for update_wrapper().
            This is a convenience function to simplify applying partial() to update_wrapper().
         """
         return partial(update_wrapper, wrapped=wrapped,
                        assigned=assigned, updated=updated)
     def update_wrapper(wrapper,
                        wrapped,
                        assigned = WRAPPER_ASSIGNMENTS,
                        updated = WRAPPER_UPDATES):
         """Update a wrapper function to look like the wrapped function wrapper is the function to be updated wrapped is the original function assigned is a tuple naming the attributes assigned directly from the wrapped function to the wrapper function (defaults to functools.WRAPPER_ASSIGNMENTS) updated is a tuple naming the attributes of the wrapper that are updated with the corresponding attribute from the wrapped function (defaults to functools.WRAPPER_UPDATES)
         """
         for attr in assigned:
             try:
                 value = getattr(wrapped, attr)
             except AttributeError:
                 pass
             else:
                 setattr(wrapper, attr, value)
         for attr in updated:
             getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
         # Issue #17482: set __wrapped__ last so we don't inadvertently copy it      
         # from the wrapped function when updating __dict__
         wrapper.__wrapped__ = wrapped
         # Return the wrapper so this can be used as a decorator via partial()
         return wrapper
相關文章
相關標籤/搜索