繁体   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