Skip to main content
 首页 » 编程设计

python之如何知道我是否在装饰一个方法

2025年05月04日9sky-heaven

调用装饰器的时候好像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 

我会知道第一个参数是否是“self”,但会有一个不那么肮脏的解决方案吗?

编辑:为什么?

我想填充可调用项及其参数的列表,如果它是一个函数或一个类,并且我可以传递预期的参数,那么我会调用它,但如果它是一个方法,我没有“ self ”要通过的参数。像这样的东西:

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 中是否有任何更改使上述行为有所不同。)