[英]how to know if I'm decorating a method
調用裝飾器時,mymethod似乎還不是一種方法。
import inspect
class decorator(object):
def __call__(self, call):
if inspect.ismethod(call): #Not working yet
obj = "method"
args = inspect.getargspec(call)[0][1:]
elif inspect.isfunction(call):
obj = "function"
args = inspect.getargspec(call)[0]
elif inspect.isclass(call):
obj = "class"
args = inspect.getargspec(call.__init__)[0][1:]
args="(%s)" % repr(args)[1:-1].replace("'","")
print "Decorate %s %s%s" % (obj, call.__name__, args)
return call
@decorator()
def myfunction (a,b): pass
@decorator()
class myclass():
def __init__(self, a, b): pass
@decorator()
def mymethod(self, a, b): pass
if inspect.isfunction(myclass.mymethod):
print "mymethod is a function"
if inspect.ismethod(myclass.mymethod):
print "mymethod is a method"
輸出:
Decorate function myfunction(a, b)
Decorate function mymethod(self, a, b)
Decorate class myclass(a, b)
mymethod is a method
我想知道第一個參數是否為“自我”,但解決方案會更臟嗎?
編輯: 為什么?
我想填充可調用對象及其參數的列表,如果它是函數或類,並且可以傳遞期望的參數,則可以調用它,但是如果它是方法,則沒有“自我”參數可以傳遞。 就像是:
import inspect
class ToDo(object):
calls=[]
def do(self, **kwargs):
for call in self.calls:
if 'self' in call.args:
print "This will fail."
args = {}
for arg in call.args:
args[arg]=kwargs.get(arg, None)
call.call(**args)
TODO = ToDo()
class decorator(object):
def __call__(self, call):
if inspect.isfunction(call):
args = inspect.getargspec(call)[0]
elif inspect.isclass(call):
args = inspect.getargspec(call.__init__)[0][1:]
self.call = call
self.args = args
TODO.calls.append(self)
return call
TODO.do(a=1, b=2)
您無法真正做到這一點。 這是一個例子:
>>> class A(object):
... pass
...
>>> def foo(x): return 3
...
>>> A.foo = foo
>>> type(foo)
<type 'function'>
>>> type(A.foo)
<type 'instancemethod'>
如您所見,您的裝飾器可以應用於foo
,因為它是一個函數。 但是,您可以簡單地創建一個引用該函數的類屬性來創建一個修飾的方法。
(此示例來自Python 2.7;我不確定Python 3是否進行了任何更改以使上述行為有所不同。)
您不能從函數中分辨出方法,但可以檢查第一個參數是否看起來像self:
def __call__(self, func):
def new_func(*args, **kw):
if len(args) and hasattr(args[0], '__dict__') \
and '__class__' in dir(args[0]) and func.__name__ in dir(args[0])\
and '__func__' in dir(getattr(args[0], func.__name__))\
and getattr(args[0], func.__name__).__func__ == self.func:
return my_func(*args[1:], **kw)
else:
return my_func(*args, **kw)
self.func = new_func
return new_func
但這對嵌套裝飾器不起作用-下一個裝飾器將更改功能,並與self.func比較不起作用。
另一種方法-檢查裝飾函數的第一個參數的名稱是否為self-這在Python中是非常嚴格的約定,因此可能就足夠了:
def __call__(self, func):
def new_func(*args, **kw):
if len(inspect.getfullargspec(func).args)\
and inspect.getfullargspec(func).args[0] == 'self':
return my_func(*args[1:], **kw)
else:
return my_func(*args, **kw)
self.func = new_func
return new_func
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.