how __name__ change in python decorator
<p>Recently I'm learning Python decorator and the use of <code>functools.wraps</code>.</p>

<pre><code>def a():
    def b():
        def c():
            print('hello')
        return c
    return b


print a.__name__
#output:a
</code></pre>

<p>I understand why the output is a.But I don't know how <code>__name__</code> change in the following code.</p>

<pre><code>def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('...')
def simple():
    print('*' * 20)

print simple.__name__
#output:wrapper
</code></pre>

<p>Why the output is 'wrapper' rather than 'decorator' or 'log'? </p>

<pre><code>@log('...')
def simple(...
</code></pre>

<p>is equivalent to</p>

<pre><code>def simple(...
simple = log('...')(simple)
</code></pre>

<p>so <code>log</code> is actually called, returning <code>decorator</code>, which is called with <code>simple</code> as argument which is then replaced by <code>decorator</code>'s return value, which is the function <code>wrapper</code>, thus its <code>__name__</code> is <code>wrapper</code>.</p>

python