How does this python decorator work?

前端 未结 3 997
孤街浪徒
孤街浪徒 2021-01-15 04:59

Edit/Clarification to make my question specific to my query: *I can see how the decorator static log function is called but I don\'t see how _ is

相关标签:
3条回答
  • 2021-01-15 05:46
    def decorate(fn):
        def wrapper():
            fn()
        print 'Wrapping function ', wrapper
        return wrapper
    
    def x():
        pass
    
    print 'Original x ', x
    
    x = decorate(x)
    
    print 'New x ', x
    

    Output:

    Original x <function x at 0x7f3c51e9a758>
    Wrapping function <function wrapper at 0x7f3c51e9a7d0>
    New x  <function wrapper at 0x7f3c51e9a7d0>
    

    Note how x is now the same as wrapper. When you call x, you are actually calling wrapper.

    Do not mark this answer as the answer. Mark one of the others as the answer. The point of this is to correct a misunderstanding so that you may then correctly understand one of the other answers.

    0 讨论(0)
  • 2021-01-15 05:48

    The fundamental fact about decorators is that

    @decorator
    def func(): ...    
    

    is exactly equivalent to

    def func(): ...
    func=decorator(func)
    

    So,

    @logger.log
    def first_x_method(self): ...
    

    is the same as

    def first_x_method(self): ...
    first_x_method=logger.log(first_x_method)
    

    and so the logger.log static method is called with argument func = first_x_method.

    Inside the call to logger.log(first_x_method), the sub method __ is defined and returned.

    first_x_method=logger.log(first_x_method) thus sets first_x_method to refer to the sub method __.

    The parenthesis in first_x_method() tells Python to call the method first_x_method.

    So x().first_x_method() first instantiates an instance of the class x, and then calls the method first_x_method (with x() supplied as the first argument).

    Since first_x_method refers to __, it is __ that gets called.

    0 讨论(0)
  • 2021-01-15 05:58

    A decorator is a function that accepts a function as an argument and returns a "decorated" function that will actually be used when it's called.

    In this case logger.log is passed the function first_x_method. The actual decorator implementation creates a function that prints a message before and after running its argument, and returns that function (in this case, called ___). So in effect, every time you call first_x_method, you're actually calling ____, which maintains a reference to first_x_method as func.

    In other words, ____ "captures" first_x_method and replaces it. Whenever it's called, it will first print something, call the function it has a reference to, and then print something again.

    edit: Maybe this simplified example can help you understand it:

    def decorate(func):
      print "Decorate called"
      def internal(*args, **kwargs):
        print "Calling internal"
        func(*args, **kwargs)
        print "Original function returned: "
      print "Created the decorated function, returning."
      return internal
    
    @decorate
    def foo(s):
      print "foo called with: ", s
      return 42
    
    foo('hello')
    
    0 讨论(0)
提交回复
热议问题