装饰一个类的特定方法

时间:2016-02-20 16:56:46

标签: python decorator static-methods

我读到了装饰器,我试图用静态方法装饰类的所有方法。

现在我只是使用我为非特定函数编写的装饰器,所以我想知道是否有一种方法来装饰很多方法但是避免使用静态方法

我的装饰师得到了什么:

TypeError: unbound method test() must be called with ClassTest instance as first argument (got nothing instead)

我的装饰者:

def decorator(func):
    def wrapper(self, *args, **kwargs):
        print "test"
        return func(self, *args, **kwargs)
    return wrapper

1 个答案:

答案 0 :(得分:1)

首先,装饰课程非常简单:

def class_decorator(cls):
    # modify cls
    return cls

为了向方法添加/删除/修改功能,您可以使用方法(或变量)的装饰版本调用setattr

setattr(some_class, some_attribute, decorator(some_callable))

至于区分不同类型的方法,您可以使用一些属性 确定方法是否是实例/类/静态方法。

一个完整的工作示例:

def _is_instance_method(var):
    if not hasattr(var, '__call__'): # It's not a callable
        return False
    if not hasattr(var, 'im_self'): # It's a callable, but it's not a bound method
        return False
    if getattr(var, 'im_self') is not None: # At this point, if it's a class method,
                                            # it will be bound to the class, while
                                            # the instance method is still unbound
                                            # return False if it's bound (i.e. a class method)
        return False
    return True # All that remains is a callable, that's boundable, but not yet -- an instance method!

def func_decorator(func):
    def func_wrapper(self, *args, **kwargs):
        print "Inside %s!" % (func.__name__,)
        return func(self, *args, **kwargs)
    return func_wrapper

def class_decorator(cls):
    for attr in cls.__dict__:
        var = getattr(cls, attr)
        if _is_instance_method(var): # Determine whether the attribute is an instance method
            setattr(cls, attr, func_decorator(var)) # Replace the function with a decorated one
    return cls # Return the class with its new decorated instance methods

@class_decorator
class B(object):

    @staticmethod
    def static_method():
        return "static method"

    @classmethod
    def cls_method(cls):
       return "cls method"

    def instance_method(self):
       return "instance method"

print B.static_method() 
print B.cls_method()
b = B()
print b.instance_method()