Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
类或函数的python装饰器_Python_Decorator - Fatal编程技术网

类或函数的python装饰器

类或函数的python装饰器,python,decorator,Python,Decorator,仅就以下内容是否合理或是否有更好的方法征求意见。基本上,我想要一个应用于函数或类的装饰器,它实现了调用 您可以使用一个常规的decorator并显式地修饰_调用,但是decorator被隐藏在类定义中,不太明显。也许我错过了一个更直接的解决方案 导入类型 从functools导入包装 12类: “”“装饰实现_;调用_;的类 或者直接使用函数。 """ 定义初始化(self,foo): self.\u foo=foo 定义呼叫(自我、目标): wrapps\u class=isinstance(

仅就以下内容是否合理或是否有更好的方法征求意见。基本上,我想要一个应用于函数或类的装饰器,它实现了调用

您可以使用一个常规的decorator并显式地修饰_调用,但是decorator被隐藏在类定义中,不太明显。也许我错过了一个更直接的解决方案

导入类型
从functools导入包装
12类:
“”“装饰实现_;调用_;的类
或者直接使用函数。
"""
定义初始化(self,foo):
self.\u foo=foo
定义呼叫(自我、目标):
wrapps\u class=isinstance(目标,类型.类类型)
如果是U类:
乐趣=目标__
其他:
乐趣=目标
@包装(乐趣)
def bar(*args,**kwds):
val=args[1]如果包装类else args[0]
打印自我。\u foo,val
返回乐趣(*args,**kwds)
如果是U类:
目标.\uuuu调用\uuuu=bar
返回目标
其他:
回程杆
@十二月(‘A’)
a类:
#你可以在这里装饰,但它似乎有点隐蔽
定义调用(self,val):
打印“传递到a:”,val
@十二月(‘B’)
def b(val):
打印“传递到b:”,val
a()(11)
b(22)

这是一个非常巧妙的想法。这对我来说似乎很好,尽管直接修饰
\uuuu调用\uuu
可能更像python,因为“显式优于隐式”。让一个装饰师做两件事会有一点概念上的开销


(我想知道,如果制作一个包含任何函数修饰符并将其转换为双函数/类修饰符的修饰符,是更糟还是更好…

我真的不喜欢你的方法。如果调用实例,则使用
\uuuu call\uuu()
方法。调用类本身会调用
\uuuu init\uuuu()
,因此我不认为这是真正类似的


您的装饰器不适用于新样式的类(直接或间接派生自
对象
)。帮你自己一个忙,如果这是你想要的,就简单地装饰一下
\uuu\u call()
。或者编写一个工厂函数来创建和装饰类的实例——这完全类似于装饰一个函数,因为该实例是可直接调用的,并且您不必乱用
self
参数。

我个人会将其分为两个装饰器:一个总是包装函数的装饰器:

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
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
另一个用于检测是否应该修改
\uuuuu调用\uuuuu
方法或简单地包装函数:

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
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
将在旧样式和新样式的类中正常工作。

谢谢。(如果有人对此感兴趣,DzinX指出,要使其与新样式类一起工作,需要使用inspect.isclass进行检查。)