You can't pass it as its own name, but you can add it to the keywords.

def decorate(function):
    def wrap_function(*args, **kwargs):
        kwargs['str'] = 'Hello!'
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message(*args, **kwargs):
    print(kwargs['str'])

Alternatively you can name its own argument:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        return function(str, *args, **kwargs)
    return wrap_function

@decorate
def print_message(str, *args, **kwargs):
    print(str)

Class method:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        args.insert(1, str)
        return function(*args, **kwargs)
    return wrap_function

class Printer:
    @decorate
    def print_message(self, str, *args, **kwargs):
        print(str)
Answer from Tor Valamo on Stack Overflow
🌐
Miguel Grinberg
blog.miguelgrinberg.com › post › the-ultimate-guide-to-python-decorators-part-iii-decorators-with-arguments
The Ultimate Guide to Python Decorators, Part III: Decorators with Arguments - miguelgrinberg.com
You may expect that decorator arguments are somehow passed into the function along with this f argument, but sadly Python always passes the decorated function as a single argument to the decorator function.
Discussions

python - Decorators with parameters? - Stack Overflow
Your example is not syntactically ... you're passing it one. Decorators are just syntactic sugar for wrapping functions inside other functions. See docs.python.org/reference/compound_stmts.html#function for complete documentation. ... Save this answer. ... Show activity on this post. The syntax for decorators with arguments is a bit different ... More on stackoverflow.com
🌐 stackoverflow.com
How do I pass extra arguments to a Python decorator? - Stack Overflow
What confuses things is that many ... outer function (myDecorator here) a decorator. This is convenient for a user of the decorator, but can be confusing when you're trying to write one. 2012-04-16T17:03:12.963Z+00:00 ... Small detail that confused me: if your log_decorator takes a default argument, you cannot use @log_decorator, it must be @log_decorator() 2020-03-11T16:26:21.723Z+00:00 ... What if I don't want to pass True to ... More on stackoverflow.com
🌐 stackoverflow.com
How does a decorator with arguments work behind the screen?
It doesn't "know", it basically just does tmp = do_sth_if_true(True), then yeah = tmp(yeah). To make this work, you want do_sth_if_true to be a function that returns a decorator. More on reddit.com
🌐 r/learnpython
7
35
October 19, 2022
python - How can I pass arguments to decorator, process there, and forward to decorated function? - Stack Overflow
I recently decided to learn Python decorators, and followed this howto. Especially the exemple under the section "passing arguments to decorators". What I want to do is (1) the decorator function s... More on stackoverflow.com
🌐 stackoverflow.com
July 17, 2016
🌐
Medium
medium.com › @rahulkp220 › even-more-python-decorators-6f283e276770
Python Decorators with arguments! | by Rahul Lakhanpal | Medium
June 27, 2016 - Simply said, the arguments passed to the outer level function “multiply” are the ones which you will/would pass to your final decorator call.
Top answer
1 of 16
1289

The syntax for decorators with arguments is a bit different - the decorator with arguments should return a function that will take a function and return another function. So it should really return a normal decorator. A bit confusing, right? What I mean is:

def decorator_factory(argument):
    def decorator(function):
        def wrapper(*args, **kwargs):
            funny_stuff()
            something_with_argument(argument)
            result = function(*args, **kwargs)
            more_funny_stuff()
            return result
        return wrapper
    return decorator

Here you can read more on the subject - it's also possible to implement this using callable objects and that is also explained there.

Usage:

@decorator_factory("Some argument")
def function_to_be_decorated(args):
    print(f"Do something with '{args}'.")

decorator_factory("Some argument") uses the given argument to create a standard, argumentless decorator. So the following block is functionally identical to the one above:

created_decorator = decorator_factory("Some argument")

@created_decorator
def function_to_be_decorated(args):
    print(f"Do something with '{args}'.")
2 of 16
559

Edit : for an in-depth understanding of the mental model of decorators, take a look at this awesome Pycon Talk. well worth the 30 minutes.

One way of thinking about decorators with arguments is

@decorator
def foo(*args, **kwargs):
    pass

translates to

foo = decorator(foo)

So if the decorator had arguments,

@decorator_with_args(arg)
def foo(*args, **kwargs):
    pass

translates to

foo = decorator_with_args(arg)(foo)

decorator_with_args is a function which accepts a custom argument and which returns the actual decorator (that will be applied to the decorated function).

I use a simple trick with partials to make my decorators easy

from functools import partial

def _pseudo_decor(fun, argument):
    def ret_fun(*args, **kwargs):
        #do stuff here, for eg.
        print ("decorator arg is %s" % str(argument))
        return fun(*args, **kwargs)
    return ret_fun

real_decorator = partial(_pseudo_decor, argument=arg)

@real_decorator
def foo(*args, **kwargs):
    pass

Update:

Above, foo becomes real_decorator(foo)

One effect of decorating a function is that the name foo is overridden upon decorator declaration. foo is "overridden" by whatever is returned by real_decorator. In this case, a new function object.

All of foo's metadata is overridden, notably docstring and function name.

>>> print(foo)
<function _pseudo_decor.<locals>.ret_fun at 0x10666a2f0>

functools.wraps gives us a convenient method to "lift" the docstring and name to the returned function.

from functools import partial, wraps

def _pseudo_decor(fun, argument):
    # magic sauce to lift the name and doc of the function
    @wraps(fun)
    def ret_fun(*args, **kwargs):
        # pre function execution stuff here, for eg.
        print("decorator argument is %s" % str(argument))
        returned_value =  fun(*args, **kwargs)
        # post execution stuff here, for eg.
        print("returned value is %s" % returned_value)
        return returned_value

    return ret_fun

real_decorator1 = partial(_pseudo_decor, argument="some_arg")
real_decorator2 = partial(_pseudo_decor, argument="some_other_arg")

@real_decorator1
def bar(*args, **kwargs):
    pass

>>> print(bar)
<function __main__.bar(*args, **kwargs)>

>>> bar(1,2,3, k="v", x="z")
decorator argument is some_arg
returned value is None
Top answer
1 of 6
242

Since you are calling the decorator like a function, it needs to return another function which is the actual decorator:

def my_decorator(param):
    def actual_decorator(func):
        print("Decorating function {}, with parameter {}".format(func.__name__, param))
        return function_wrapper(func)  # assume we defined a wrapper somewhere
    return actual_decorator

The outer function will be given any arguments you pass explicitly, and should return the inner function. The inner function will be passed the function to decorate, and return the modified function.

Usually you want the decorator to change the function behavior by wrapping it in a wrapper function. Here's an example that optionally adds logging when the function is called:

def log_decorator(log_enabled):
    def actual_decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            if log_enabled:
                print("Calling Function: " + func.__name__)
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

The functools.wraps call copies things like the name and docstring to the wrapper function, to make it more similar to the original function.

Example usage:

>>> @log_decorator(True)
... def f(x):
...     return x+1
...
>>> f(4)
Calling Function: f
5
2 of 6
62

Just to provide a different viewpoint: the syntax

@expr
def func(...): #stuff

is equivalent to

def func(...): #stuff
func = expr(func)

In particular, expr can be anything you like, as long as it evaluates to a callable. In particular particular, expr can be a decorator factory: you give it some parameters and it gives you a decorator. So maybe a better way to understand your situation is as

dec = decorator_factory(*args)
@dec
def func(...):

which can then be shortened to

@decorator_factory(*args)
def func(...):

Of course, since it looks like decorator_factory is a decorator, people tend to name it to reflect that. Which can be confusing when you try to follow the levels of indirection.

🌐
GeeksforGeeks
geeksforgeeks.org › decorators-with-parameters-in-python
Decorators with parameters in Python - GeeksforGeeks
August 27, 2024 - In this article, we will try to ... examples. What is Decorator In Python?A decorator is a function that can take a function as an argument and extend its functionality an ......
🌐
Real Python
realpython.com › lessons › decorating-functions-arguments
Decorating Functions With Arguments (Video) – Real Python
There’s a standardized way to do that. Let’s rewrite this. 03:46 You’re going to add *args and **kwargs—which stands for arguments and keyword arguments—to your decorator.
Published: March 19, 2019
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › how does a decorator with arguments work behind the screen?
r/learnpython on Reddit: How does a decorator with arguments work behind the screen?
October 19, 2022 -

I am learning python decorators and having some doubts with decorators with arguments. I will try to make my point clear (Or my doubts, better say) with examples:

If I execute the following piece of code:

def do_function_twice(func):
	print("Inside decorator")
	@functools.wraps(func)
	def wrapper(*arg):
		print("Inside wrapper")
		func(*arg)
		return func(*arg)
	return wrapper

@do_function_twice
def print_msg(msg):
	print(msg)
	return f"What is up buddy"

I receive Inside decorator as I was expecting, because behind the scenes python did print_msg = do_function_twice(print_msg)

What if I try creating a decorator with an argument like the following?

def do_sth_if_true(bool_):
	print("Inside do_sth_if_true")
	def repeat_func(func):
		print("Inside repeat_func")
		func()
		return func()
	return repeat_func

@do_sth_if_true(True)
def yeah():
	print("Yeah")

If I execute the script I receive:

Inside do_sth_if_true
Inside repeat_func
Yeah
Yeah

I can imagine it is doing yeah = do_sth_if_true(True)(yeah) behind the scenes (So it is calling the wrapping function, in this example called repeat_func. My question would be: How does python know which way to apply the decorator?

Top answer
1 of 4
8
It doesn't "know", it basically just does tmp = do_sth_if_true(True), then yeah = tmp(yeah). To make this work, you want do_sth_if_true to be a function that returns a decorator.
2 of 4
5
So under the hood all a decorator is is a function that returns a function. The handy syntax basically says "give the function I'm about to define to this other function and store the result of that as the name of the original function" Decorators with arguments are just a little special though. Under the hood what happens is the decorator siphons off the arguments first then the underlying function. Or in code this is happening: @some_decorator def my_func(arg1, arg2): pass Is turning into: def my_func(arg1, arg2): pass my_func = some_decorator(my_func) And with arguments: @some_decorator(arg1) def my_func(arg2, arg3): pass Turns into: def my_func(arg2, arg3): pass my_func = some_decorator(arg1)(my_func) The practical application of the above means that for decorators with arguments they no longer turn the modified function, but return a function that then returns a function that does the modification. In other words they curry (aka partial argument application) the arguments passed to the decorator and then pass the function to the result. Remember that a decorator is a function that returns a function, which is still true here. Just instead of literally wrapping the function you're making a call to get the thing to use to wrap it first (hence parenthesis). >>> def dec(f): ... def w(): ... print("wrapped!") ... return f() ... return w ... >>> @dec ... def my_func(): ... print("hi") ... >>> my_func() wrapped! hi >>> def dec_factory(arg): ... def dec(f): ... def w(): ... print(f"wrapped with {arg}!") ... return f() ... return w ... return dec ... >>> @dec_factory("arguments") ... def my_func(): ... print("hi") ... >>> my_func() wrapped with arguments! hi
🌐
DEV Community
dev.to › apcelent › python-decorator-tutorial-with-example-529f
Python Decorator with Arguments: Python Decorator Tutorial with Example - DEV Community
July 30, 2018 - Prepending @ to the name of the decorator, and writing the same above a function calls the decorator, and passes the function to the decorator(decorates).
Top answer
1 of 2
6

The reason is immediate after considering how the decorator transforms the function and that functions are objects themselves in Python.

Let's start from the latter.

Functions are objects:

This is immediate when we consider the meaning of two pairs of parenthesis after a function name. Consider this simple example (Python 3):

def func(x):
    def func2(y):
        return x + y + 1
    return func2

result = func(5)(10)
print(result)  # 15

Here "func" returns a function object "func2" and therefore you can use:

func(5)(10)

You can view this as calling first

func(5)

and applying "(10)" to the resulting object that is a function! So you have:

func2(10)

Now since both "x" and "y" are defined, "func2" can return the final value to "result".

Remember, this is all possible because functions are object themselves and because "func" returns a function object

func2

and not its result (it is not invoking the function on its own)

func2()

In short, that means that with wrapped functions the second set of arguments is for the inner function (if the wrapper returns the inner function object).

Decorators:

In your example, "main" calls "fun1" in the last line with

return fun1(decarg)

Due to the decorator

@dec(decarg)

In reality you can think of "fun1" as:

fun1 = dec(decarg)(fun1)

Therefore, the last line in "main" is equivalent to:

return dec(decarg)(fun1)(decarg)

With the previous explanation it should be trivial to find the problem!

  • dec(decarg) gets executed and returns a "_dec" function object; note that this "decarg" is the one passed in the first parenthesis and thus in the decorator.
  • _dec(fun1) gets executed and returns a "_fun" function object.
  • _fun(decarg) gets executed and invokes fun1(decargs) with the return statement and this will correctly translate in fun1(3) that is the result you get; note that this "decarg" is the one passed in the third parenthesis and thus when you invoke "fun1" in main.

You don't get 13 as a result because you don't invoke "fun1" with the result from

funarg = decarg + 7

as argument, but rather you invoke it with "decarg" that is passed to "_fun" as positional argument (funarg=decarg) from main.

Anyway, I have to thank you for this question, because I was looking for a neat way to pass an argument to a decorator only when invoking a function, and this works very nicely.

Here is another example that might help:

from functools import wraps

def add(addend):
    def decorator(func):
        @wraps(func)
        def wrapper(p1, p2=101):
            for v in func(p1, p2):
                yield v + addend
        return wrapper
    return decorator


def mul(multiplier):
    def decorator(func):
        @wraps(func)
        def wrapper(p1, p2=101):
            for v in func(p1, p2):
                yield v * multiplier
        return wrapper
    return decorator


def super_gen(p1, p2=101, a=0, m=1):
    @add(a)
    @mul(m)
    def gen(p1, p2=101):
        for x in range(p1, p2):
            yield x
    return gen(p1, p2)
2 of 2
1

Ok here is a simple explaination:

A simple decorator (no parameters) is a function that takes a function as argument and returns another function that will be called in place of the original one

A decorator that accepts a parameter is a function that takes that parameter and returns a simple decorator

Here you can build a simple decorator that adds 7 to the parameter of the decorated function:

def add7(func):
    '''takes a func and returns a decorated func adding 7 to its parameter'''
    def resul(x):
        return func(x + 7)
    return resul

You can use it that way:

def main(mainarg):
    decarg = mainarg + 2
    @add7
    def fun1(funarg):
        return funarg+3
    return fun1(decarg)

main(1)

it returns as expected 13.

But you can easily build a parameterized decorator that will add an arbitrary value, but adding a level for processing the parameter:

def adder(incr):
    '''Process the parameter (the increment) and returns a simple decorator'''
    def innerdec(func):
        '''Decorator that takes a function and returns a decorated one
that will add the passed increment to its parameter'''
        def resul(val):
            return func(val + incr)
        return resul
    return innerdec

You will then use it that way

 def main(mainarg):
    decarg = mainarg + 2
    @adder(7)
    def fun1(funarg):
        return funarg + 3
    return fun1(decarg)

main(1)

still returns 13

🌐
SitePoint
sitepoint.com › blog › programming › understanding python decorators, with examples
Understanding Python Decorators, with Examples — SitePoint
November 6, 2024 - Having parameters passed to the ... for manipulating the decorated function. Any number of arguments (*args) or keyword arguments (**kwargs) can be passed unto the decorated function....
🌐
GitHub
gist.github.com › Zearin › 2f40b7b9cfc51132851a
The best explanation of Python decorators I’ve ever seen. (An archived answer from StackOverflow.)
Look:', arg1, arg2 function_to_decorate(arg1, arg2) return a_wrapper_accepting_arguments # Since when you are calling the function returned by the decorator, you are # calling the wrapper, passing arguments to the wrapper will let it pass them to # the decorated function @a_decorator_passing_arguments def print_full_name(first_name, last_name): print 'My name is', first_name, last_name print_full_name('Peter', 'Venkman') # outputs: #I got args! Look: Peter Venkman #My name is Peter Venkman · One nifty thing about Python is that methods and functions are really the same.
Top answer
1 of 3
13

As others wrote here, a decorator is a syntactic sugar (i.e., makes programs easier to read, write, or understand) of a function that receives another function as a parameter and activates it from inside.

So, calling this “Add()” function with the decorator, like this:

@wrapper()
def Add(x: int, y: int):
    return x + y

It is just like calling the “wrapper” function with the “Add” function as a variable. Like this:

 wrapper(Add)(x,y) # pass x,y to wrapper that pass it to Add function.
|wrapper|
|----Add----|()

The best way (I think) to add parameters to a decorator, is by nesting it all under another function that holds a child decorator. For example:

@deco_maker(msg: str)
def Add(x: int, y: int):
    return x + y

will be this:

 deco_maker(msg)(Add)(x,y)
|--wrapper-|
|-wrapper_func-|
|---------Add-------|

Here is a simple wrapper decorator that log's function calls, without parameters, which can look like this:

def wrapper(func: Callable):
    def wrapper_func(*args, **kwargs):
        logging.DEBUG f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}."
        value = func(*args, **kwargs)
        return value
    return wrapper_func

and here is the extended decorator with relevant logging parameters (log name and level for more flexibility):

def log_func_calls(logger_name: str, log_level: int):
    def wrapper(func: Callable):
        def wrapper_func(*args, **kwargs):
            logger = logging.getLogger(logger_name)
            logger.log(
                    level=log_level,
                    msg=f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}."
                    )
            value = func(*args, **kwargs)
            return value
        return wrapper_func
    return wrapper

Here is a full code example for a parameterized decorator for logging function calls, and the log file output print after it.

Example:

import logging
from typing import Callable

# define app logger with file and console handlers
def setup_logging():
    logger = logging.getLogger('test_app')
    logger.setLevel(logging.DEBUG)
    # create file handler which logs even debug messages
    fh = logging.FileHandler('test.log')
    fh.setLevel(logging.DEBUG)
    # create formatter and add it to the file handler
    formatter = logging.Formatter('{asctime} | {name} | {levelname:^8s} | {message}', style='{')
    fh.setFormatter(formatter)
    # add the handler to the logger
    logger.addHandler(fh)
    return logger

# define a log decorator to trace function calls
def log_func_calls(logger_name: str, log_level: int):
    def wrapper(func: Callable):
        def wrapper_func(*args, **kwargs):
            logger = logging.getLogger(logger_name)
            logger.log(
                    level=log_level,
                    msg=f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}."
                    )
            value = func(*args, **kwargs)
            return value
        return wrapper_func
    return wrapper

# sample usage 1
@log_func_calls(logger_name='test_app', log_level=logging.DEBUG)
def Add(x: int, y: int):
    return x + y

# sample usage 2
@log_func_calls(logger_name='test_app', log_level=logging.DEBUG)
def Sub(x: int, y: int):
    return x - y

# a test run
def main():
    logger = setup_logging()
    logger.info("<<< App started ! >>>")
    print(Add(50,7))
    print(Sub(10,7))
    print(Add(50,70))
    logger.info("<<< App Ended ! >>>")

if __name__ == "__main__":
    main()

And the log output:

...
2022-06-19 23:34:52,656 | test_app |  DEBUG   | Function 'Add' called with args: ['50', '7'].
2022-06-19 23:34:52,656 | test_app |  DEBUG   | Function 'Sub' called with args: ['10', '7'].
2022-06-19 23:34:52,657 | test_app |  DEBUG   | Function 'Add' called with args: ['50', '70'].
...
2 of 3
0

the short answer is no but you can modify the code of the decorator function; for example:

def decorator(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

this is a standard decorator function, let's change it a little.

you could do something like this:

def decorator(func,defaultdescription,defaultnum):
    def inner(description=defaultdescription,num=defaultnum,*args,**kwargs):
        print("function",func.__code__.co_name,"with description",description,"with number",num)
        return func(*args,**kwargs)

    return inner

so you can change the description of the function

🌐
CodingNomads
codingnomads.com › python-decorators-with-arguments
Python Decorators With Arguments
The function syntax with parentheses is required for passing the argument while decorating the function · Want to get into Data Science, Machine Learning or AI? Data Science and Machine Learning are two of the most useful skills you can develop ...
🌐
Real Python
realpython.com › primer-on-python-decorators
Primer on Python Decorators – Real Python
September 1, 2026 - The wrapper function uses *args and **kwargs to pass on arguments to the decorated function. If you want your decorator to also take arguments, then you need to nest the wrapper function inside another function.
🌐
MuirlandOracle
muirlandoracle.co.uk › 2021 › 06 › 28 › python-decorators-tutorial
Python Decorators -- Tutorial | MuirlandOracle | Blog
These special parameters allow us to capture every argument and keyword argument passed into a function, which means we can pass them straight through to the decorated function: #!/usr/bin/env python3 import getpass def authenticator(func): def processor(*args, **kwargs): username = input("What is your username?
🌐
Better Programming
betterprogramming.pub › how-to-write-python-decorators-that-take-parameters-b5a07d7fe393
How to Write Python Decorators That Take Parameters | by Yong Cui | Better Programming
May 13, 2020 - To use this decorator function, we use the @ symbol as the prefix to the decorator function name (i.e., echo_wrapper) right above the function that is to be decorated. When we call the decorated…
🌐
Python Tutorial
pythontutorial.net › home › advanced python › python decorator with arguments
Python Decorator with Arguments
March 27, 2025 - from functools import wraps def repeat(fn): @wraps(fn) def wrapper(*args, **kwargs): for _ in range(5): result = fn(*args, **kwargs) return result return wrapper @repeat def say(message): ''' print the message Arguments message: the message to show ''' print(message) say('Hello')Code language: Python (python) ... What if you want to execute the say() function repeatedly ten times. In this case, you need to change the hard-coded value 5 in the repeat decorator.
🌐
Medium
adamdonaghy.medium.com › python-decorators-an-idiots-guide-1a41b62990c7
Python Decorators — A beginners guide | by Adam Donaghy | Medium
April 4, 2019 - Python decorators are a super powerful way to apply generic logic to functions by wrapping them in another function. This makes them perfect for applying generic logic to functions, Django views (like custom authentication) and a bunch of other ...
🌐
pythontutorials
pythontutorials.net › blog › how-can-i-pass-a-variable-in-a-decorator-to-function-s-argument-in-a-decorated-function
How to Pass a Variable from a Python Decorator to a Decorated Function's Argument — pythontutorials.net
To avoid pitfalls when passing variables from decorators: Explicitly Declare Injected Parameters: Always have the decorated function accept injected variables as parameters (avoids silent bugs). Use Keyword-Only Arguments: Prefix injected parameters with * (e.g., def func(*, injected_var)) to enforce keyword-only usage and prevent positional clashes.