In Python, create a decorator that dynamically accepts arguments Create a decorator

background

If you define and use your own decorator in Python, you may want to be able to pass arguments to the decorator later.

Where to use the original decorator


@my_decorator
def hoge():
	# ...

If you implement a general decorator, you'll want to be able to pass arguments to the decorator later. It will be necessary to rewrite all the decorators that were used like ↑ as ↓.

When setting arguments when using a decorator


@my_decorator(arg1='value1')
def hoge():
	# ...

Even if you don't need any arguments, you need to put parentheses if the decorator implementation changes.

When no argument is set when using the decorator


@my_decorator()
def hoge():
	# ...

Rewriting all the parts that use the decorator is bothersome to modify and verify, so I wanted it to work without the parentheses if no arguments were needed.

Purpose

I want to create a decorator (my_decorator) that can dynamically use arguments as shown below. By the way, I would like to implement it as a decorator for decorators so that such functions can be used universally.

python


#With no arguments
@my_decorator
def hoge():
	pass

#With arguments
@my_decorator(arg1='value1')
def fuga():
	pass

Implementation

Implement a decorator that dynamically interprets the arguments to apply to the decorator, as shown below.

decorators.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import functools


def dynamic_args(func0):
    def wrapper(*args, **kwargs):
        if len(args) != 0 and callable(args[0]):
            #When a function is passed as the first argument:Treat as a decorator with no arguments
            func = args[0]
            return functools.wraps(func)(func0(func))
        else:
            #Other:Treat as a decorator with arguments
            def _wrapper(func):
                return functools.wraps(func)(func0(func, *args, **kwargs))
            return _wrapper
    return wrapper

Usage image

If you prepare a decorator like the one above, you can achieve your purpose simply by defining your own decorator as follows.

python


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from decorators import dynamic_args


#Apply the decorator created above to your decorator
@dynamic_args
def my_decorator(func, arg1='default_value1', arg2='default_value2'):
    def wrapper(*args, **kwargs):
    	#Defined arguments(arg1, arg2)Write the process you want to actually do using
    	# ...
    return wrapper

Usage sample

As a sample, create a decorator named my_decorator that puts parentheses before and after the return value (string).

sample.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from decorators import dynamic_args


#####################
#Your own decorator definition#
#####################
@dynamic_args
def my_decorator(func, before='「', after='」'):
    def wrapper(*args, **kwargs):
        return "{} {} {}".format(before, func(*args, **kwargs), after)
    return wrapper


##########################
#Example of using a decorator with no arguments#
##########################
@my_decorator
def func_without_args():
    return "Argumentless decorator"

print(func_without_args()) # output:"Decorator with no arguments"


##########################
#Example of using a decorator with arguments#
##########################
@my_decorator(before='『', after='』')
def func_with_args():
    return "Decorator with arguments"

print(func_with_args()) # output:"Decorator with arguments"


####################################
#An example of applying a decorator to a predefined function#
####################################
def func_without_decorator():
    return "No decorator"


print(my_decorator(func_without_decorator)()) # output:"No decorator"
print(my_decorator(before="『", after="』")(func_without_decorator)()) # output:"No decorator"

reference

Python Tips: I want to pass arguments to the decorator-Life with Python http://www.lifewithpython.com/2016/09/python-decorator-with-arguments.html

Python Decorator Expressions (2)-When decorators have arguments and you want to apply multiple decorators | Immediately forget your brain notes for that http://jutememo.blogspot.jp/2008/10/python-2.html

python - AttributeError: 'str' object has no attribute 'module' - Stack Overflow http://stackoverflow.com/questions/18493879/attributeerror-str-object-has-no-attribute-module

Recommended Posts

In Python, create a decorator that dynamically accepts arguments Create a decorator
Create a function in Python
Create a dictionary in Python
Create a fake class that also cheats is instance
In Python, create a decorator that dynamically accepts arguments Create a decorator
Create a DI Container in Python
Create a binary file in Python
Create a Python general-purpose decorator framework
Create a Kubernetes Operator in Python
Create a random string in Python
Give a Python decorator an alias that passes fixed arguments
Let's create a script that registers with Ideone.com in Python.
Create code that outputs "A and pretending B" in python
[Python / Django] Create a web API that responds in JSON format
Create a JSON object mapper in Python
[Python] Create a LineBot that runs regularly
[GPS] Create a kml file in Python
Let's create a customer database that automatically issues a QR code in Python
Create a Vim + Python test environment in 1 minute
Create a GIF file using Pillow in Python
I want to create a window in Python
Create a standard normal distribution graph in Python
How to create a JSON file in Python
Create a virtual environment with conda in Python
Create a page that loads infinitely with python
Create a simple momentum investment model in Python
Python: Create a class that supports unpacked assignment
Create a new page in confluence with Python
Create a datetime object from a string in Python (Python 3.3)
Create a package containing global commands in Python
Create a MIDI file in Python using pretty_midi
Create a loop antenna pattern in Python in KiCad
[Docker] Create a jupyterLab (python) environment in 3 minutes!
Create SpatiaLite in Python
Create a Python environment
I tried to create a class that can easily serialize Json in Python
Create a plugin that allows you to search Sublime Text 3 tabs in Python
I want to create a priority queue that can be updated in Python (2.7)
Create a data collection bot in Python using Selenium
[LINE Messaging API] Create a rich menu in Python
Create a plugin to run Python Doctest in Vim (2)
Create a plugin to run Python Doctest in Vim (1)
What's in that variable (when running a Python script)
Create a fake Minecraft server in Python with Quarry
MALSS, a tool that supports machine learning in Python
Take a screenshot in Python
Create a Wox plugin (Python)
Dynamically import scripts in Python
Create gif video in Python
Make a bookmarklet in Python
Create a python numpy array
Dynamically call methods in Python
Draw a heart in Python
Create a directory with python
A general-purpose program that formats Linux command strings in python
Create a local scope in Python without polluting the namespace
A function that divides iterable into N pieces in Python
Published a library that hides character data in Python images
Create a list in Python with all followers on twitter
Loop through a generator that returns a date iterator in Python
[Python] Create a linebot that draws any date on a photo
Create a child account for connect with Stripe in Python