classification
Title: Decorated (inner/wrapped) function kwarg defaults dont pass through decorator.
Type: behavior Stage: resolved
Components: Versions: Python 3.6, Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: ssmeke, steven.daprano
Priority: normal Keywords:

Created on 2018-06-07 05:12 by ssmeke, last changed 2018-06-07 06:15 by steven.daprano. This issue is now closed.

Messages (2)
msg318892 - (view) Author: Salomon Smeke (ssmeke) Date: 2018-06-07 05:12
I am seeing an issue when attempting to use default kwargs in decorated functions.

I would post reproduction steps, but instead I have written a snippet which should showcase the issue.

Snippet:
```python
def decorator():
    def inner(f):
        def wrapper(*args, **kwargs):
            # Zoinks, Scoob!
            print('Decorator: {}'.format(''.join(kwargs.values())))
            print(f(*args, **kwargs))
        return wrapper
    return inner

@decorator()
def func(foo='wont print in the decorator'):
    return 'Func: {}'.format(foo)```

The following calls to 'func' should show you what Im talking about clearly:

```
func()
-> Decorator: 
-> Func: wont print in the decorator
func(foo='will print in the decorator')
-> Decorator: will print in the decorator
-> Func: will print in the decorator
```

I would expect, though correct me if I am wrong, that both of these calls should print in the decorator and the function call.

For convenience, some REPL.it links:
3.6.1 -> https://repl.it/@SalomonSmeke/Python3-Decorator-Bug
2.7.10 -> https://repl.it/@SalomonSmeke/Python-Decorator-Bug

Using @wrap from functools:
2.7.10 -> https://repl.it/@SalomonSmeke/Python-Decorator-Bug-using-FuncTools

Thank you for your time.

P.S.
This is my first issue submitted to Python, please let me know if there is detail lacking. Im happy to provide what I can.
msg318896 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2018-06-07 06:15
I think you have misunderstood where and when default arguments are assigned. When you call func() with no arguments, kwargs is empty, and it is correct that the output will be

-> Decorator: 

In the following line, you call the original function, f(), again with no arguments. Then, and ONLY then, is the default argument for foo applied. Only the innermost function "func" knows that there is a parameter called foo with the given default. Hence the next output is 

-> Func: wont print in the decorator

as that is applying the default.

So I think the behaviour is correct. It is certainly the behaviour I would expect, so unless I'm misunderstanding your bug report, I think this is working as designed.

I'm going to close this report now, but if you think I've misunderstood anything and want to reopen it with more details, please do so.
History
Date User Action Args
2018-06-07 06:15:34steven.dapranosetstatus: open -> closed

nosy: + steven.daprano
messages: + msg318896

resolution: not a bug
stage: resolved
2018-06-07 05:12:25ssmekecreate