Python decorator decorates the method of the class

Python decorator decorates the method of the class

When writing a crawler with scrapy, a decorator is needed to decorate the parse method in the Spider class, but the self.parse function is used in the parse method. I was worried that the decorator would modify the entry of the function self.parse, so I made a Test, found that the decorator is still very stable.

test code

check is a decorator for a method in a class (not a class method), so self is a positional parameter that must be written, and response is the positional parameter when it is called.
The value of response is monitored here. If it is 401, it will output the address of self.parse and call it with the parameter 300. If it is not 200, output the address of self.parse, end, and no longer call the function itself. If the response is 200, the function itself will be called, and the parameters will be passed in. Note that self is written here.
Spider is a class with a method called parse, which is decorated by check.
The test case, first output the address of self.parse, and tried three times with three samples.
Output self.parse multiple times to see if the address has changed.
Three sample meanings:

  • 200: Look at the result of the decorator running the inner function correctly.
  • 203: The input of this parameter, after being decorated, will produce different behaviors.
  • 401: It will output its own information first, and then call the method with response=300

Use the next call of 401 to compare the results of 200 and 203 above: if the result is the same as 200, it means that the decorator cannot handle the callback function well; if the result is the same as 203, it means that the decorator is fine.
The result is the latter.

in conclusion

Once a method in a class is decorated with a decorator, its invocation entry permanently becomes the entry of the decorator. You can use it with confidence, all kinds of calls are no problem.

import functools
def check(func):
    @functools.wraps(func)
    def inner(self, response, *args, **kwargs):
        if response == 401:
            print(401)
            print(self.parse)
            print("**************************")
            self.parse(300)
        elif response != 200:
            print(200)
            print(self.parse)
            print("**************************")
        else:
            return func(self, response, *args, **kwargs)
    return inner


class Spider():
    @check
    def parse(self, response):
        print('foo')

if __name__ == '__main__':
    s = Spider()
    print(s.parse)
    s.parse(200)
    print("--------------------")
    s.parse(203)
    print("--------------------")
    s.parse(401)

The output is as follows:

<bound method Spider.parse of <__main__.Spider object at 0x000001AAFB9A7320>>
foo
--------------------
200
<bound method Spider.parse of <__main__.Spider object at 0x000001AAFB9A7320>>
**************************
--------------------
401
<bound method Spider.parse of <__main__.Spider object at 0x000001AAFB9A7320>>
**************************
200
<bound method Spider.parse of <__main__.Spider object at 0x000001AAFB9A7320>>
**************************

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324690793&siteId=291194637