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!

相关文章
|
4天前
|
Go C++ Python
Python Tricks: String Conversion(Every Class Needs a ___repr__)
Python Tricks: String Conversion(Every Class Needs a ___repr__)
15 5
|
4天前
|
前端开发 Python
Python Tricks-- Abstract Base Classes Keep Inheritance in Check
Python Tricks-- Abstract Base Classes Keep Inheritance in Check
|
4天前
|
C++ Python
Python Tricks--- Object Comparisons:“is” vs “==”
Python Tricks--- Object Comparisons:“is” vs “==”
10 1
|
4天前
|
Python
Python Tricks: Nothing to Return Here
Python Tricks: Nothing to Return Here
|
4天前
|
C# Python
Python Tricks : Function Argument Unpacking
Python Tricks : Function Argument Unpacking
10 1
|
4天前
|
Linux Go Python
Python Tricks :The Power Of Decorators
Python Tricks :The Power Of Decorators
10 1
|
4天前
|
API Python
Python Tricks : Fun With args and kwargs
Python Tricks : Fun With args and kwargs
|
4天前
|
Go C# Python
Python Tricks :Lambdas Are Single-Expression Functions 原创
Python Tricks :Lambdas Are Single-Expression Functions 原创
|
2天前
|
人工智能 数据挖掘 Serverless
探索Python编程:从基础到实战
【10月更文挑战第2天】本文将带你走进Python的世界,了解它的基本语法、数据结构、函数等核心概念,并通过实例演示如何应用这些知识解决实际问题。无论你是编程新手还是有一定经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python编程之旅吧!
|
1天前
|
开发者 Python
Python 语法糖:让编程更简单
Python 语法糖:让编程更简单
13 3