为什么在Python代码中需要装饰器

Python is praised for its clarity and syntactic sugariness. In this article, I will teach you to use decorators in Python to make your code readable and clean.

Python的清晰性和语法含糖度受到赞誉。 在本文中,我将教您在Python中使用装饰器,以使您的代码更具可读性和简洁性。

什么是装饰器? (What Are Decorators?)

To understand what decorators are, you first need to be familiar with the way Python handles functions. From its point of view, functions are no different than regular objects. They have properties and can be reassigned:

要了解装饰器是什么,首先需要熟悉Python处理函数的方式。 从它的角度来看,功能与常规对象没有什么不同。 它们具有属性,可以重新分配:

Moreover, you can pass them as arguments to other functions:

此外,您可以将它们作为参数传递给其他函数:

Now, to decorators. A decorator is used to modify the behaviour of a function or class. The way this is achieved is by defining a function (decorator) that returns another function. This sounds complicated, but you will understand everything with this example:

现在,到装饰员。 装饰器用于修改函数或类的行为。 实现此方法的方法是定义一个函数(装饰器),该函数返回另一个函数。 这听起来很复杂,但是您将通过此示例理解所有内容:

Let’s go step by step:

让我们一步一步走:

  • Firstly, we define the logging_decorator function on line 1. It accepts a single argument, which is the function we are trying to decorate.

    首先,我们在第1行上定义logging_decorator函数。它接受一个参数,这是我们尝试修饰的函数。

  • Inside, we define another function: the logging_wrapper. The logging_wrapper is then returned and used in place of the original decorated function.

    在内部,我们定义了另一个函数: logging_wrapper 。 然后返回logging_wrapper并代替原始的装饰函数。

  • On line 7, you can see how the decorator is applied to the sum function.

    在第7行,您可以看到装饰器如何应用于sum函数。

  • On line 11, when we call sum, it will not just call sum. It will call the logging_wrapper, which will log before and after calling the sum.

    在第11行,当我们调用sum ,它不仅会调用sum 。 它将调用logging_wrapper ,它将在调用sum之前和之后进行记录。

为什么需要装饰器? (Why Do You Need Decorators?)

It is simple: readability. Python is praised for its clear and concise syntax, and decorators are no exceptions. If there is any behaviour that is common to more than one function, you probably need to make a decorator. Here are some examples of when they might come in handy:

很简单:可读性。 Python因其简洁明了的语法而广受赞誉,装饰器也不例外。 如果有多个功能共有的行为,则可能需要制作装饰器。 以下是一些可能派上用场的示例:

  • Checking argument type at runtime

    在运行时检查参数类型
  • Benchmark function calls

    基准函数调用
  • Cache function results

    缓存功能结果
  • Count function calls

    计算函数调用
  • Checking metadata (permissions, roles, etc.)

    检查元数据(权限,角色等)
  • Metaprogramming

    元编程
  • And much more…

    以及更多…

Now I will list some code examples.

现在,我将列出一些代码示例。

具有返回值的装饰器 (Decorators With Return Values)

Suppose we want to know how long each function call takes. Also, functions return something most of the time, so the decorator must handle that as well:

假设我们想知道每个函数调用要花费多长时间。 而且,函数大多数时候会返回某些东西,因此装饰器也必须处理该问题:

You can see we store the returned value in result on line 5. But before returning it, we have to finish timing the function. This is an example of behaviour that would not be possible without decorators.

您可以看到我们将返回的值存储在第5行的result中。但是在返回它之前,我们必须完成对函数的计时。 这是没有装饰器就无法实现的行为示例。

带参数的装饰器 (Decorators With Arguments)

Sometimes, we want a decorator that accepts values (like @app.route('/login') in Flask):

有时,我们需要一个接受值的装饰器(例如Flask中的@app.route('/login') ):

In order to achieve that, we defined an extra function that accepts an argument and returns a decorator.

为了实现这一点,我们定义了一个额外的函数,该函数接受一个参数并返回一个装饰器。

用课堂装饰 (Decorating With Classes)

It is possible to decorate using classes instead of functions. The only difference is the syntax, so do what you are more comfortable with. Here is the logging decorator rewritten using classes:

可以使用类而不是函数进行装饰。 唯一的区别是语法,所以您更喜欢它。 这是使用类重写的日志装饰器:

The upside is that you do not have to deal with nested functions. All you need to do is define a class and override the __call__ method.

好处是您不必处理嵌套函数。 您需要做的就是定义一个类并覆盖__call__方法。

装饰类 (Decorating Classes)

There may be times when you want to decorate each and every method in a class. You could always write it like this:

有时您可能想装饰一个类中的每个方法。 您总是可以这样写:

But if you have lots of methods, this can get out of hand. Thankfully, there is a way to decorate the whole class at once:

但是,如果您有很多方法,这可能会一发不可收拾。 值得庆幸的是,有一种方法可以一次装饰整个类:

Now, do not panic. This looks complicated, but this is the same logic:

现在,不要惊慌。 这看起来很复杂,但这是相同的逻辑:

  • Firstly, we leave the logging_decorator as is. It will be applied to all methods of a class.

    首先,我们保持logging_decorator 。 它将应用于类的所有方法。

  • Then we define a new decorator: log_all_class_methods. It is like a regular decorator but returns a class instead.

    然后,我们定义一个新的装饰器: log_all_class_methods 。 它就像一个普通的装饰器,但是返回一个类。

  • The NewCls has a custom __getattribute__. For all calls to the original class, it will decorate the functions with the logging_decorator.

    NewCls有一个自定义__getattribute__ 。 对于所有对原始类的调用,它将使用logging_decorator装饰函数。

内置装饰器 (Built-In Decorators)

Not only can you define your own decorators, but there are some shipped in the standard library as well. I will list the three that I have worked with the most:

您不仅可以定义自己的装饰器,而且标准库中也有一些装饰器。 我将列出我工作最多的三个人:

  • @property — A decorator from built-ins that lets you define getters and setters for class properties.

    @property property-内置的装饰器,可让您定义类属性的getter和setter。

  • @lru_cache — A decorator from the functools module. It memorizes function arguments and return values, which is handy for pure functions (like the factorial).

    @lru_cachefunctools模块中的装饰器。 它存储函数参数和返回值,这对于纯函数(例如factorial )非常方便。

  • @abstractmethod — A decorator from the abc module. Indicates that the method is abstract and implementation details are missing.

    @abstractmethod —来自abc模块的装饰器。 表示该方法是抽象的,并且缺少实现细节。

结束语 (Closing Notes)

Thank you for reading, I hope you liked my article. Stay subscribed for more Python content!

感谢您的阅读,希望您喜欢我的文章。 请继续订阅更多Python内容!

翻译自: https://medium.com/better-programming/why-you-need-decorators-in-your-python-code-df12d43eac9c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值