An article Python decorators get to know all the uses (recommended collection)

 

96 
I love to learn python  
 1.8  2019.05.30 16:38  Words 3071  Read 164 reviews 2

01. decorator syntax sugar

If you touch Python for some time, then surely you are no strangers to the @ sign, right @ symbol is syntactic sugar decorator.

Place it in a function defined at the beginning, it's like a hat worn on the head of this function. And the function to bind together. When we call this function, the first thing is not to perform this function, but this function as a parameter passed it the hat on his head, the hat we call decorative function or decorator.

You want to ask me what the decorator function can be achieved? I can only say how big the hole in your brain, there are more powerful decorator.

Use decorator is fixed:

Define a decorative function (hat) (class may also be used, to achieve partial function)

And then define your business function or class (people)

Finally this hat with the man in the head

Simple usage decorator there are many here cite two common.

Log the printer

Timer

02. Getting Started Usage: log printer unit

First, the printer logs.

Realization of functions:

Before the function execution, the first print line of the log to inform about the owner, I want to perform a function.

In the function executed, we can not quit the jobs, and we but polite code, and then print the next line of the log to inform the owner, I am done for execution.

 

 

If my business function is to calculate the sum of the two numbers. After written, it directly to a hat.

 

 

Then we calculated it.

add(200,50)

Come see what the output, not magic?

 

 


03. Getting Started Usage: timer

Look at the timer

Function: As the name suggests, is a long time to perform a calculation function.

 

 

If, our function is to sleep 10 seconds. Long in the end do not fly when this can be better seen in this calculation.

 

 

Take a look at the output. Jesus really is 10 seconds. Really calendar harm! ! !

 

 


04. Advanced Usage: decorator function with parameters

By the above simple entry, you probably have felt the magic of the decoration.

However, the use of decorators is far more than that. Today, it is imperative that we thoroughly publicize knowledge.

上面的例子,装饰器是不能接收参数的。其用法,只能适用于一些简单的场景。不传参的装饰器,只能对被装饰函数,执行固定逻辑。

如果你有经验,你一定经常在项目中,看到有的装饰器是带有参数的。

装饰器本身是一个函数,既然做为一个函数都不能携带函数,那这个函数的功能就很受限。只能执行固定的逻辑。这无疑是非常不合理的。而如果我们要用到两个内容大体一致,只是某些地方不同的逻辑。不传参的话,我们就要写两个装饰器。小明觉得这不能忍。

那么装饰器如何实现传参呢,会比较复杂,需要两层嵌套。

同样,我们也来举个例子。

我们要在这两个函数的执行的时候,分别根据其国籍,来说出一段打招呼的话。

 

 

在给他们俩戴上装饰器的时候,就要跟装饰器说,这个人是哪国人,然后装饰器就会做出判断,打出对应的招呼。

戴上帽子后,是这样的。

 

 

万事俱备,只差帽子了。来定义一下,这里需要两层嵌套。

 

 

执行一下

 

 

看看输出结果。

 

 

emmmm,这很NB。。。

05. 高阶用法:不带参数的类装饰器

以上都是基于函数实现的装饰器,在阅读别人代码时,还可以时常发现还有基于类实现的装饰器。

基于类装饰器的实现,必须实现 __call__ 和 __init__两个内置函数。

__init__ :接收被装饰函数

__call__ :实现装饰逻辑。

 

 

执行一下,看看输出

 

 


06. 高阶用法:带参数的类装饰器

上面不带参数的例子,你发现没有,只能打印INFO级别的日志,正常情况下,我们还需要打印DEBUG WARNING等级别的日志。 这就需要给类装饰器传入参数,给这个函数指定级别了。

带参数和不带参数的类装饰器有很大的不同。

__init__ :不再接收被装饰函数,而是接收传入参数。

__call__ :接收被装饰函数,实现装饰逻辑。

 

 

我们指定WARNING级别,运行一下,来看看输出。

 

 


07. 使用偏函数与类实现装饰器

绝大多数装饰器都是基于函数和闭包实现的,但这并非制造装饰器的唯一方式。

事实上,Python 对某个对象是否能通过装饰器( @decorator)形式使用只有一个要求:decorator 必须是一个“可被调用(callable)的对象。

对于这个 callable 对象,我们最熟悉的就是函数了。

除函数之外,类也可以是 callable 对象,只要实现了__call__ 函数(上面几个盒子已经接触过了),还有比较少人使用的偏函数也是 callable 对象。

接下来就来说说,如何使用 类和偏函数结合实现一个与众不同的装饰器。

如下所示,DelayFunc 是一个实现了 __call__ 的类,delay 返回一个偏函数,在这里 delay 就可以做为一个装饰器。(以下代码摘自 Python工匠:使用装饰器的小技巧)

 

 

我们的业务函数很简单,就是相加

 

 

来看一下执行过程

 

 


08. 如何写能装饰类的装饰器?

用 Python 写单例模式的时候,常用的有三种写法。其中一种,是用装饰器来实现的。

以下便是我自己写的装饰器版的单例写法。

 

 

可以看到我们用singleton 这个装饰函数来装饰 User 这个类。装饰器用在类上,并不是很常见,但只要熟悉装饰器的实现过程,就不难以实现对类的装饰。在上面这个例子中,装饰器就只是实现对类实例的生成的控制而已。

其实例化的过程,你可以参考我这里的调试过程,加以理解。

 

09. wraps 装饰器有啥用?

在 functools 标准库中有提供一个 wraps 装饰器,你应该也经常见过,那他有啥用呢?

先来看一个例子

 

 

为什么会这样子?不是应该返回 func 吗?

这也不难理解,因为上边执行func 和下边 decorator(func) 是等价的,所以上面 func.__name__ 是等价于下面decorator(func).__name__ 的,那当然名字是 inner_function

 

 

那如何避免这种情况的产生?方法是使用 functools .wraps 装饰器,它的作用就是将 被修饰的函数(wrapped) 的一些属性值赋值给 修饰器函数(wrapper) ,最终让属性的显示更符合我们的直觉。

 

 

准确点说,wraps 其实是一个偏函数对象(partial),源码如下

 

 

可以看到wraps其实就是调用了一个函数update_wrapper,知道原理后,我们改写上面的代码,在不使用 wraps的情况下,也可以让 wrapped.__name__ 打印出 wrapped,代码如下:

 

 


10. 内置装饰器:property

以上,我们介绍的都是自定义的装饰器。

其实Python语言本身也有一些装饰器。比如property这个内建装饰器,我们再熟悉不过了。

它通常存在于类中,可以将一个函数定义成一个属性,属性的值就是该函数return的内容。

通常我们给实例绑定属性是这样的

 

 

但是稍有经验的开发人员,一下就可以看出,这样直接把属性暴露出去,虽然写起来很简单,但是并不能对属性的值做合法性限制。为了实现这个功能,我们可以这样写。

 

 

上面的代码设计虽然可以变量的定义,但是可以发现不管是获取还是赋值(通过函数)都和我们平时见到的不一样。

按照我们思维习惯应该是这样的。

 

 

那么这样的方式我们如何实现呢。请看下面的代码。

 

 

用@property装饰过的函数,会将一个函数定义成一个属性,属性的值就是该函数return的内容。同时,会将这个函数变成另外一个装饰器。就像后面我们使用的@age.setter和@age.deleter。

@age.setter 使得我们可以使用XiaoMing.age = 25这样的方式直接赋值。

@age.deleter 使得我们可以使用del XiaoMing.age这样的方式来删除属性。

property 的底层实现机制是「描述符」,为此我还写过一篇文章。

这里也介绍一下吧,正好将这些看似零散的文章全部串起来。

如下,我写了一个类,里面使用了 property 将 math 变成了类实例的属性

 

 

Why is the underlying property descriptor-based protocol it? Click to enter the property through PyCharm source, unfortunately, but a similar pseudo-source document the same, and there is no specific implementation logic.

However, the dummy source from this magic function structures can generally know the implementation logic.

Here I function by mimicking its structure, combined with "descriptor Agreement" to achieve their own class property characteristics.

code show as below:

 

 

Then the Student class, we also changed accordingly as follows

 

 

To try to make you wonder a little bit less, I'm here to do just two points:

After use TestProperty decoration, Math is no longer a function, but an instance of the class TestProperty. So the second math function can be used to decorate math.setter, essentially calling TestProperty.setter to create a new instance of TestProperty assigned to the second math.

The first and second math math TestProperty are two different instances. But they all belong to the same class descriptor (TestProperty), when for the assignment of math, will enter TestProperty .__ set__, when the value of math were in, will enter TestProperty .__ get__. A closer look, in fact, the final visit or Student _math attribute instance.

Having said that, it is still running, a little more intuitive.

 

 

Such as the principle of running the above code, the students in question, be sure to combine the above two instructions to be understood that two points are critical.

11. Other decorator: the decorator combat

Read and understand the contents of the above, you can say that Python master. Do not doubt, self-confidence point, because many people do not know there are so many decorators use it.

In my opinion, the decorator, can achieve the following objectives:

Make the code more readable, grid higher force;

Code structure clearer, less redundancy codes;

I also have just recently in a scene, you can use a good decorator to achieve, for the time being not impress a look.

This is a realization of the control function operation timeout decorator. If the timeout, timeout exception will be thrown.

Interested can look at.

 

 

Guess you like

Origin www.cnblogs.com/cheyunhua/p/10954448.html