[英]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.