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