Methods decorated with a decorator class do not have the "self" argument frozen

I have a decorator declared as a class:

class predicated(object):
    def __init__(self, fn):
        self.fn = fn
        self.fpred = lambda *args, **kwargs: True

    def predicate(self, predicate):
        self.fpred = predicate
        return self

    def validate(self, *args, **kwargs):
        return self.fpred(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if not self.validate(*args, **kwargs):
            raise PredicateNotMatchedError("predicate was not matched")
        return self.fn(*args, **kwargs)

... and when I use it to transfer a method to a class, calling this method does not seem to set the object instance as the first argument. Although this behavior is not entirely unexpected, how can I make it freeze selfwhen a method becomes an instance method?


A simplified example:

class test_decorator(object):
    def __init__(self, fn):
        self.fn = fn
    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

class Foo(object):
    @test_decorator
    def some_method(self):
        print(self)

Foo().some_method()

The expected instance of foo, instead we get an error in which 0 arguments are passed.

+5
source share
1 answer

It turned out - you need to define a method __get__for creating a binding MethodType, for example:

def __get__(self, obj, objtype=None):
    return MethodType(self, obj, objtype)

MethodType , self.

+4

All Articles