簡體   English   中英

類OR函數的python decorator

[英]python decorator for class OR function

只是征求關於以下是否合理或是否有更好的方法的意見。 基本上我想要一個將應用於函數或實現__call__的類的裝飾器。

你可以只有一個普通的裝飾器並明確地裝飾__call__但是裝飾器隱藏在類定義中並且不太明顯。 也許我錯過了一個更簡單的解決方案。

import types
from functools import wraps

class dec:
    """ Decorates either a class that implements __call__ 
        or a function directly.
    """
    def __init__(self, foo):
        self._foo = foo

    def __call__(self, target):
        wraps_class = isinstance(target, types.ClassType)
        if wraps_class:
            fun = target.__call__
        else:
            fun = target

        @wraps(fun)
        def bar(*args, **kwds):
            val = args[1] if wraps_class else args[0]
            print self._foo, val
            return fun(*args, **kwds)
        if wraps_class:
            target.__call__ = bar
            return target
        else:
            return bar

@dec('A')
class a:
    # you could decorate here, but it seems a bit hidden
    def __call__(self, val):
        print "passed to a:", val

@dec('B')
def b(val):
    print "passed to b:", val

a()(11)
b(22)

就個人而言,我會把它分成兩個裝飾器:一個總是包裝一個函數:

def func_dec(foo, is_method=False):
    def wrapper(fun):
        @wraps(fun)
        def bar(*args, **kwds):
            val = args[1] if is_method else args[0]
            print foo, val
            return fun(*args, **kwds)
        return bar
    return wrapper

另一個檢測它是否應該修改__call__方法或只是包裝一個函數:

def dec(foo):
    def wrapper(obj):
        if inspect.isclass(obj):
            obj.__call__ = func_dec(foo, is_method=True)(obj.__call__)
            return obj
        else:
            return func_dec(foo)(obj)
    return wrapper

請注意, inspect.isclass將在舊式和新式類中正確運行。

我真的不喜歡你的方法。 如果調用實例,則使用__call__()方法。 調用類本身會調用__init__() ,所以我不認為這是非常類似的。

您的裝飾器不適用於新式類(直接或間接從object派生)。 幫自己一個忙,如果這就是你想要的,只需裝飾__call__() 或者編寫一個創建和修飾類實例的工廠函數 - 這完全類似於裝飾一個函數,因為實例可以直接調用,而且你不必使用self參數混淆arounf。

這是一個非常漂亮的想法。 這對我來說似乎很好,雖然直接裝飾__call__可能更加pythonic,因為“顯式優於隱式”。 讓一個裝飾器完成兩件事有一些概念上的開銷。

(我想知道裝飾器是否需要任何函數裝飾器並將其轉換為雙重函數/類裝飾器會更糟或更好......)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM