Python类方法装饰器

时间:2015-12-12 16:02:12

标签: python python-decorators

我为类方法

编写了一个装饰器
def decor(method):
    def wrapped(self, *args, **kwargs):
        return method(self, *args, **kwargs)
    # [*]
    return wrapped

我想用这个:

class A(metaclass=mymetaclass):
    @decor
    def meth(self):
        pass

如何在装饰器中添加方法/变量到具有装饰方法的类?我需要在[*]附近做。 在内部包裹我可以写self.__class__,但在这里做什么?

5 个答案:

答案 0 :(得分:5)

我无法想象一种满足这种要求的方法,因为decor函数只接收一个对包含类一无所知的函数对象。

我能想象的唯一解决方法是使用参数化装饰器并将其传递给正在装饰的类

def decor(cls):
    def wrapper(method):
        def wrapped(self, *args, **kwargs):
            return self.method(*args, **kwargs)
        print method   # only a function object here
        return wrapped
    print cls  # here we get the class and can manipulate it
    return wrapper

class A
    @decor(A)
    def method(self):
        pass

或者,您可以自己修饰类:

def cdecor(cls):
    print 'Decorating', cls  # here we get the class and can manipulate it
    return cls

@cdecor
class B:
    def meth(self):
        pass

给出:

Decorating __main__.B

答案 1 :(得分:0)

根据这一回应,它看起来似乎不可能直接成为可能:

Get Python function's owning class from decorator

你可以做的是为你的班级提供装饰,类似的东西:

class InsertMethod(object):
    def __init__(self, methodToInsert):
        self.methodToInsert = methodToInsert

    def __call__(self, classObject):
        def wrapper(*args, **kwargs):
            setattr(classObject, self.methodToInsert.__name__, self.methodToInsert)
            return classObject(*args, **kwargs)
        return wrapper

def IWillBeInserted(self):
    print "Success"


@InsertMethod(IWillBeInserted)
class Something(object):
    def __init__(self):
        pass

    def action(self):
        self.IWillBeInserted()


a = Something()
a.action()

答案 2 :(得分:0)

实际上,你可以装饰这个类本身:

def class_decorator(class_):
    class_.attribute = 'value'
    class_.method = decorate(class_.method)
    return class_

@class_decorator
class MyClass:
    def method(self):
        pass

答案 3 :(得分:0)

我聚会晚了一点,但是迟到总比不到好吗? :)

我们可以通过用一个装饰器(它本身是一个类对象,例如B)装饰我们的类方法,然后挂接到Python调用B.__get__的那一刻来获取该方法来做到这一点。在将通过所有者类和该类的新生成的实例传递的__get__调用中,您可以选择将方法/变量插入原始所有者类或新定义的实例中。 / p>

class B(object):
    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        return self.f(*args, **kwargs)

    def __get__(self, instance, owner):

        instance.inserted = True
        # owner.inserted = True
        def wrapper(*args, **kwargs):
            return self(instance, *args, **kwargs)
        return wrapper

class A:
    @B
    def method(self):
        pass

if __name__ == "__main__":
    a = A()
    a.method()
    b = A()

    print(hasattr(a, 'inserted'))
    print(hasattr(b, 'inserted'))

在此示例中,我们用def method(self)包装@B。如所写,插入的属性inserted将仅在a对象中保留,因为它被应用于实例。如果如图所示创建第二个对象b,则不包含inserted属性。 IE,hasattr(a, 'inserted')打印True,而hasattr(b, 'inserted')打印False。但是,如果我们将inserted应用于owner类(如注释行所示),则插入的属性将持久存在于所有将来的A()对象中。 IE hasattr(a, 'inserted')打印True,而hasattr(b, 'inserted')打印True,因为b是在调用a.method()之后创建的。

答案 4 :(得分:0)

您似乎只是想装饰一个类函数,而不是@classmethod。这是我想在函数返回成功结果时调用类保存函数的一种简单方法:

def save_on_success(func):
    """ A decorator that calls a class object's save method when successful """
    def inner(self, *args, **kwargs):
        result = func(self, *args, **kwargs)
        if result:
            self.save()
        return result
    return inner

以下是使用方式的示例:

class Test:
    def save(self):
            print('saving')
    @save_on_success
    def test(self, var, result=True):
            print('testing, var={}'.format(var))
            return result

进行测试以确保其可以正常工作:

>>> x = Test()
>>> print(x.test('test True (should save)', result=True))
testing, var=test True (should save)
saving
True
>>> print(x.test('test False (should not save)', result=False))
testing, var=test False (should not save)
False