Python Tricks : How to Write Debuggable Decorators

简介: Python Tricks : How to Write Debuggable Decorators

Python Tricks: How to Write “Debuggable” Decorators
When you use a decorator, really what you’re doing is replacing one funciton with another. One downside of this process is that it “hides” some of the metadata attached to the original(undecorated) function.

For example, the original function name, its doctoring, and parameter list are hidden by the wrapper closure:

In [4]: def uppercase(func):
   ...:     def wrapper():
   ...:         original_result = func()
   ...:         modified_result = original_result.upper()
   ...:         return modified_result
   ...:     return wrapper
In [1]: def greet():
   ...:     """Return a friendly greeting."""
   ...:     return 'Hello!'

In [2]: decorated_greet = uppercase(greet)

If you try to access any of that function metadata, you’ll see the wrapper closure’s metadata instead:

In [6]: greet.__name__
Out[6]: 'greet'

In [7]: greet.__doc__
Out[7]: 'Return a friendly greeting.'

In [8]: decorated_greet.__name__
Out[8]: 'wrapper'

In [9]: decorated_greet.__doc__
None

This makes debugging and working with the Python interpreter awkward and challenging. Thankfully there’s a quick fix for this: the functools.wraps decorator included in Python’s standard library.

You can use functors.wrapsin your own decorators to copy over the lost metadata from the undecorated function to the decorator closure.

Here’s an example:

import functools

def uppercase(func):
    @functools.wraps(func)
    def wrapper():
        return func().upper()
    return wrapper

Applying functools.wraps to the wrapper closure returned by the decorator carries over the doctoring and other metadata of the input function:

greet.__name__
'greet'

greet.__doc__
'Return a friendly greeting.'

As a best practice, I’d recommended that you use functools.wraps in all of the decorators you write yourself. It doesn’t take much time and it will save you (and others) debugging headaches down the road.

Oh, and congratulations–you’ve made it all the way to the end of this complicated chapter and learned a whole lot about decorators in Python. Great job!

相关文章
|
1月前
|
Python
探索Python中的装饰器(Decorators)
探索Python中的装饰器(Decorators)
27 0
|
1月前
|
开发者 Python
深入理解Python中的装饰器(Decorators)
深入理解Python中的装饰器(Decorators)
20 0
|
1月前
|
监控 Python
深入理解Python中的装饰器(Decorators)
深入理解Python中的装饰器(Decorators)
|
2月前
|
Go C++ Python
Python Tricks: String Conversion(Every Class Needs a ___repr__)
Python Tricks: String Conversion(Every Class Needs a ___repr__)
22 5
|
2月前
|
前端开发 Python
Python Tricks-- Abstract Base Classes Keep Inheritance in Check
Python Tricks-- Abstract Base Classes Keep Inheritance in Check
16 1
|
2月前
|
C++ Python
Python Tricks--- Object Comparisons:“is” vs “==”
Python Tricks--- Object Comparisons:“is” vs “==”
21 1
|
2月前
|
Python
Python Tricks: Nothing to Return Here
Python Tricks: Nothing to Return Here
17 1
|
2月前
|
C# Python
Python Tricks : Function Argument Unpacking
Python Tricks : Function Argument Unpacking
27 1
|
2月前
|
Linux Go Python
Python Tricks :The Power Of Decorators
Python Tricks :The Power Of Decorators
18 1
|
2月前
|
API Python
Python Tricks : Fun With args and kwargs
Python Tricks : Fun With args and kwargs
15 0
下一篇
DataWorks