This article is [python] Movement of decorator that can be understood this time ① Decorator that does not receive arguments is a continuation.
The goal of this article is to understand the following forms of decorators:
def deco(a):
#processing
@deco(a="hello")
def test():
#processing
Let's check the behavior of the decorator ** that receives ** arguments with a minimum of code.
def foo(b):
pass
def deco(a):
print(a)
return foo
@deco(a="hello")
def test():
pass
#Execution result
# hello
Let's look at each line. Lines 1-6 just define the function, so nothing happens.
When the 8th line @ deco (a =" hello ") is reached, deco (a =" hello ") is executed first.
Lines 4-6 The function deco is executed, and when" hello "is passed to a, the character string hello is output.
And it returns the function foo.
The inside of my head is like ↓.
Because deco (a =" hello ") of @ deco (a =" hello ") is executed and the function foo is returned,
deco (a =" hello ") has been replaced with foo, and the 8th line is now @ foo.
To summarize so far,
When the code reaches @deco (argument), deco (argument) is executed first
From this point onward, [python] movement of the decorator that can be understood this time ① Decorator that does not receive arguments ** Exactly the same as steps 1 to 3 **. So I'll take a quick look after that. Please read ↑ for detailed movements.
def foo(func):
print(func.__name__)
return func
def deco(a):
print(a)
return foo
@deco(a="hello")
def test():
print("inside test func")
pass
test()
#output
# hello
# test
On line 8, deco (a =" hello ") is executed as in step 1, and the function foo is returned after hello is output.
At this point replace @ deco (a =" hello ") with @ foo in your head.
foo is a function that outputs the \ _ \ _ name \ _ \ _ attribute of func and returns func.
If you replace @ deco (a =" hello ") with @ foo in your head, you will find the function foo after @.
The function on the line following @ is passed as the first argument of the function after @ (in this case foo).
Therefore, in terms of image,
deco (a =" hello ") is executed at the time of @ deco (a =" hello ").deco (a =" hello ") is executed, hello is output and the function foo is returned.@ deco (a =" hello ") can be considered as @ foo.test immediately after @ foo is definedtest is passed as an argument to the function foo and foo is executed.foo (= function test) is assigned to the variable test.inside test func is output.It feels like.
The point is that ** the function deco must return a function (callable) **.
This is because an error occurs because it cannot be called without returning a function.
Example) If the return statement of the deco function is set to return 123, an error will occur when trying to call the int type 123 like 123 (test) at number 5 in the above image.
def deco(a):
print(a)
return 123
@deco(a="hello")
def test():
print("inside test func")
pass
#result
# hello
# Traceback (most recent call last):
# File "test.py", line 5, in <module>
# @deco(a="hello")
# TypeError: 'int' object is not callable
The image is as follows.
deco (a =" hello ") is executed and 123 is returned@ deco (a =" hello ") to @ 123 in your headtest is defined because there isdef test ():immediately after @ 123.123 (test) is executed and 'int' object is not callable is output. This is because 123 is not a function and cannot be called.def foo(func):
print(func.__name__)
return "aaa"
def deco(a):
print(a)
return foo
@deco(a="hello")
def test():
print("inside test func")
pass
test()
#result
# hello
# test
# Traceback (most recent call last):
# File "test.py", line 17, in <module>
# test()
# TypeError: 'str' object is not callable
The image looks like the following.
deco (a =" hello ") is executed and the function foo is returned@ deco (a =" hello ") with @ foo in your headtest is defined after @ footest is passed to function foofoo returns the string"aaa"" aaa " is stored in the variable testtest () is doing"aaa" (),'str' object is not callable is output. This error occurs because " aaa " is not a function.If you are not sure, it is recommended to experiment with it because it will be easier to understand the movement.
Recommended Posts