[Python] The movement of the decorator that can be understood this time ② The decorator that receives the argument

Introduction

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.

First the function after @ is executed

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,

After that, it is exactly the same as a decorator that does not receive arguments

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,

  1. deco (a =" hello ") is executed at the time of @ deco (a =" hello ").
  2. When deco (a =" hello ") is executed, hello is output and the function foo is returned.
  3. From now on, @ deco (a =" hello ") can be considered as @ foo.
  4. The function test immediately after @ foo is defined
  5. The function test is passed as an argument to the function foo and foo is executed.
  6. The return value of foo (= function test) is assigned to the variable test.
  7. When test () is executed, 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.

Experiment / error collection (Understanding progresses by playing with various things)

If deco does not return a function (callable)

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.

  1. deco (a =" hello ") is executed and 123 is returned
  2. Rewrite @ deco (a =" hello ") to @ 123 in your head
  3. The function test is defined because there isdef test ():immediately after @ 123.
  4. 123 (test) is executed and 'int' object is not callable is output. This is because 123 is not a function and cannot be called.

If the return value of the function returned by deco is not a function (callable)

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.

  1. deco (a =" hello ") is executed and the function foo is returned
  2. Replace @ deco (a =" hello ") with @ foo in your head
  3. The function test is defined after @ foo
  4. Function test is passed to function foo
  5. Function foo returns the string"aaa"
  6. The string " aaa " is stored in the variable test
  7. Since test () is doing"aaa" (),'str' object is not callable is output. This error occurs because " aaa " is not a function.

at the end

If you are not sure, it is recommended to experiment with it because it will be easier to understand the movement.

Recommended Posts

[Python] The movement of the decorator that can be understood this time ② The decorator that receives the argument
[Python] A program to find the number of apples and oranges that can be harvested
This and that of python properties
Investigation of DC power supplies that can be controlled by Python
A function that measures the processing time of a method in python
[Python3] Define a decorator to measure the execution time of a function
Python standard module that can be used on the command line
[Python] A program that finds the maximum number of toys that can be purchased with your money
This and that of the inclusion notation.
[Python] A program that calculates the number of socks to be paired
Must-see for new engineers! The technical characteristics of your company that can be understood through web training!
Article that can be a human resource who understands and masters the mechanism of API (with Python code)
Put the Python implementation module "pyDEM" of the Cross-mapping model that can estimate the non-linear time series causality in the Macbook
[Python3] Code that can be used when you want to change the extension of an image at once
Tensorflow, it seems that even the eigenvalues of the matrix can be automatically differentiated
A class for PYTHON that can be operated without being aware of LDAP
This is the only basic review of Python ~ 1 ~
This is the only basic review of Python ~ 2 ~
This is the only basic review of Python ~ 3 ~
At the time of python update on ubuntu
About the * (asterisk) argument of python (and itertools.starmap)
[Python] I examined the practice of asynchronous processing that can be executed in parallel with the main thread (multiprocessing, asyncio).
Summary of statistical data analysis methods using Python that can be used in business
Geographic information visualization of R and Python that can be expressed in Power BI
[Python] Introduction to web scraping | Summary of methods that can be used with webdriver
[Python] A program that counts the number of valleys
Features that can be extracted from time series data
Python knowledge notes that can be used with AtCoder
Why is the first argument of [Python] Class self?
The attitude that programmers should have (The Zen of Python)
[Python] A program that compares the positions of kangaroos.
List the classes that can be referenced by ObjCClass
the zen of Python
Format summary of formats that can be serialized with gensim
As you may know, Python can be written like this
Basic knowledge of DNS that can not be heard now
Processing of python3 that seems to be usable in paiza
Grep so that grep does not appear at the time of grep
Consideration for Python decorators of the type that passes variables
Goroutine (parallel control) that can be used in the field
One liner that randomly rewrites the startup time of cron
Decorator that displays "FIN method name" at the end of the method
[Python3] Call by dynamically specifying the keyword argument of the function
Goroutine that can be used in the field (errgroup.Group edition)
Scripts that can be used when using bottle in Python
Iterator that can scan forward from the middle of the sequence
Precautions that must be understood when building a PYTHON environment
I investigated the pretreatment that can be done with PyCaret
Evaluation index that can be specified in GridSearchCV of sklearn
A Python script that compares the contents of two directories
The mystery of the number that can be seen just by arranging 1s-The number of repunits and mysterious properties-
I bought and analyzed the year-end jumbo lottery with Python that can be executed in Colaboratory
Understand the probabilities and statistics that can be used for progress management with a python program
Python Priority Queuing The mystery of the result of the heapify function that most people wouldn't be interested in
・ <Slack> Write a function to notify Slack so that it can be quoted at any time (Python)
Predict the number of cushions that can be received as laughter respondents with Word2Vec + Random Forest