python 装饰器装饰类_Python装饰器指南

python 装饰器装饰类

Decorators are one of the coolest features of Python, and one of my favorites. A decorator takes a function, adds another functionality, and returns the improved function.

装饰器是Python最酷的功能之一,也是我的最爱之一。 装饰器采用一个功能,添加另一个功能,然后返回改进的功能。

But before we dive into its characteristics and uses, we must first understand a few basic things.

但是,在深入研究其特性和用途之前,我们必须首先了解一些基本知识。

介绍 (Introduction)

Everything in Python is an object. Yes, everything!

Python中的所有内容都是一个对象。 是的,一切!

Functions are not an exception. And since they are objects, they can be passed as arguments to other functions and also be returned as a result. They also have some attributes, such as __name__ and __doc__.

功能也不例外。 由于它们是对象,因此它们可以作为参数传递给其他函数,也可以作为结果返回。 它们还具有一些属性,例如__name____doc__

A function is a group of statements that performs a specific task. It helps to organize our code, it avoids repetition and makes the code reusable.

函数是一组执行特定任务的语句。 它有助于组织代码,避免重复并使代码可重用。

def function_name(args):
'''docstring'''
statements(s)

The syntax of a function is very simple. It starts with the keyword def, followed by its unique name, some parameters, and finally a semicolon. It can have a documentation (docstring) to describe what the function does.

函数的语法非常简单。 它以关键字def开头,后跟其唯一名称,一些参数,最后是一个分号。 它可以具有描述函数功能的文档(文档字符串)。

All the statements that follow make the function body and must have the correct indentation. In the end, it can contain a return statement as well.

后面的所有语句均构成函数主体,并且必须具有正确的缩进。 最后,它还可以包含一个return语句。

Output:

输出:

start of program.
name: basic_function
doc: Basic function doc
basic function: 1
end of program: 2

A function is also a callable object. In general, a callable object is something that can be called. You can check if an object is callable using the built-in function callable().

函数也是可调用对象。 通常,可调用对象是可以调用的对象。 您可以使用内置函数callable()检查对象是否可callable()

装饰工 (Decorators)

Back to decorators. As once defined, a decorator is simply a function that receives a function, does something, and then returns another function.

回到装潢师。 一旦定义,装饰器就是一个简单的函数,它接收一个函数,执行某些操作,然后返回另一个函数。

If you run this program:

如果运行此程序:

start program
basic function
wrapper function
basic function
end program

Let’s understand what just happened here. The decorator function is, as the name suggests, our decorator. It receives a function as a parameter, called func. Yes, very original names. Inside our function, we declared another function called wrapper. You don’t have to declare it inside, but it’s easy to manage.

让我们了解一下这里发生了什么。 顾名思义,装饰decorator功能就是我们的装饰器。 它接收一个函数作为参数,称为func 。 是的,非常原始的名字。 在函数内部,我们声明了另一个函数wrapper 。 您不必在内部声明它,但是它很容易管理。

This wrapper function just calls the original function passed as argument to the decorator, but you can add any functionality that you want to do.

wrapper函数仅调用作为参数传递给装饰器的原始函数,但是您可以添加要执行的任何功能。

In the end, the wrapper function is returned. Remember, we still want a callable object. Now, this new function can be called, with our original functionality and new code added to it.

最后,返回wrapper函数。 记住,我们仍然需要一个可调用的对象。 现在,可以调用此新功能,并为其添加原始功能和新代码。

But Python has a syntax to simplify this declaration. To decorate a function, you use the @ symbol along with the name of the decorator and put it above the function you want to be decorated.

但是Python具有简化该声明的语法。 要装饰一个函数,请使用@符号以及装饰器的名称,并将其放在要装饰的函数上方。

Output:

输出:

decorator func
start of program...
before func wrapped
wrapped func
after func wrapped
end of program

You can use the same decorator with any number of functions you want, and also decorate a function with any decorators you want.

您可以将同一个装饰器与所需的任何数量的功能一起使用,也可以使用任何所需的装饰器来装饰一个功能。

And output:

并输出:

decorator 2
decorator 1
decorator 1
>> start
before func
before func
basic 1
before func
basic 2
>> end

When you have multiple decorators on a function, they are called in the opposite order they are declared. That is:

当一个函数上有多个装饰器时,它们的声明顺序相反。 那是:

@decorator_1
@decorator_2
def wrapped():

Is the same as:

是相同的:

a = decorator_1(decorator_2(wrapped))

If the decorated function returns a value, and you want to preserve this property, you just have to make the value from the decorated function is returned by the wrapper function.

如果修饰的函数返回一个值,并且您想要保留此属性,则只需使修饰函数的值由包装函数返回即可。

对装饰器进行分类 (Class a decorator)

By adding the __call__ method to a class, you turn it into a callable object. And since a decorator is just a function, and therefore, a callable object, you can make a class into a decorator by implementing the function __call__.

通过将__call__方法添加到类中,可以将其变成可调用对象。 并且由于装饰器只是一个函数,因此也是一个可调用的对象,因此您可以通过实现__call__函数将一个类变成装饰器。

Confusing? Let’s see an example.

令人困惑? 让我们来看一个例子。

And as an output:

并作为输出:

> Decorator class __init__
>> start
> before call from class... wrapped
wrapped func
> after call from class
>> end

The difference here is that the class is instantiated at the declaration. It should receive a function as an argument for the __init__ method. This is the function that is being decorated.

此处的区别在于,该类是在声明处实例化的。 它应该接收一个函数作为__init__方法的参数。 这是正在装饰的功能。

When we call the decorated function, we are actually calling the class’ instance object. And since the object is a callable, the function __call__ is called.

当我们调用装饰函数时,实际上是在调用类的实例对象。 并且由于对象是可调用的,因此将__call__函数。

带参数的功能 (Function with arguments)

But what if the function you are trying to decorate must receive some arguments? Easy, just return a function that has the same signature as the function you are trying to decorate.

但是,如果您要装饰的函数必须接收一些参数怎么办? 简单,只需返回一个与您要修饰的函数具有相同签名的函数。

Output:

输出:

> decorator args...
> decorator args...
>> start
before calling func add
wrapped 1
after calling func add
ret: 15
before calling func sub
wrapped 2
after calling func sub
ret: 5
>> end

About with class? Follow the same rule. Just add the signature you want to the __call__ function.

关于上课? 遵循相同的规则。 只需将所需的签名添加到__call__函数即可。

Output:

输出:

> Decorator class __init__
>> start
> before call from class... wrapped
wrapped func: 10 20
> after call from class
>> end

You can use the *args and **kwargs also for the “wrapper” function if you don’t know the signature or must accept multiple types of functions.

如果您不知道签名或必须接受多种类型的功能,也可以将*args**kwargs用于“包装器”功能。

带参数的装饰器 (Decorators with arguments)

You can also pass a parameter to the decorator itself. In this case, you have to add an another layer of abstraction, that is, another wrapper function to return.

您还可以将参数传递给装饰器本身。 在这种情况下,您必须添加另一个抽象层,即要返回的另一个包装器函数。

This is necessary since the argument is passed to the decorator. Then this returned function is actually used to decorate the function we want. Again, this is easy to understand with an example.

这是必需的,因为参数已传递给装饰器。 然后,此返回的函数实际上用于装饰我们想要的函数。 同样,通过示例很容易理解这一点。

With output:

输出:

> decorator_with_args: test
>> real decorator for func add
start program
>>> before func add
>>>> add function
>>> after func add
20
end program

In class decorators, we have to make a similar adjustment. Now the class constructor will receive all decorator arguments. The __call__ method now should return a function, a wrapper that will in fact execute the function being decorated. Example:

在类装饰器中,我们必须进行类似的调整。 现在,类构造器将接收所有装饰器参数。 现在, __call__方法应该返回一个函数,一个包装器实际上将执行被修饰的函数。 例:

Output:

输出:

> Decorator args class __init__: teste
>> start
>>> before wrapper function
add func: 10 20
>>> after wrapper fnction
>> end

文献资料 (Documentation)

One attribute of a function is its documentation string (or docstring), accessed by __doc__ attribute. It is a string constant defined as the first statement in the function definition.

函数的一个属性是其文档字符串(或docstring),可通过__doc__属性访问。 它是一个字符串常量,定义为函数定义中的第一条语句。

When decorated, we are actually returning a new function, with other attributes. But we don’t want to alter them.

装饰后,我们实际上将返回具有其他属性的新函数。 但是我们不想更改它们。

In this example, the wrapped function is actually the decorated function, as it has been substituted by it.

在此示例中, wrapped函数实际上是decorated函数,因为它已被它替换。

start of program...
decorated
Decorated function
end of program

Here is where the function wraps from the module functools comes to rescue. It preserves the original function attributes. You only have to decorate your wrapper function with it.

这是从functools模块wraps的函数进行救援的地方。 它保留了原始函数的属性。 您只需要用它来装饰wrapper函数。

And now, the output:

现在,输出:

start of program...
wrapped
Wrapped function
end of program

应用领域 (Applications)

Until now, we didn’t really used the decorator with real applications or with real uses. But where can use them? Let’s see some examples.

直到现在,我们还没有真正将装饰器用于实际应用程序或实际用途。 但是在哪里可以使用它们呢? 让我们看一些例子。

定时 (Timing)

A basic use is to get the processed time of a function. You get the time before and after the function call and can then use this time as you want (to a log, to a database, to debug, etc).

基本用途是获取函数的处理时间。 您可以获得函数调用之前和之后的时间,然后可以根据需要使用此时间(用于日志,数据库,调试等)。

Output:

输出:

start program
add 10 20 0
>> function add_with_delay processed time (ms): 0.015000000000000001
add 10 20 1
>> function add_with_delay processed time (ms): 1000.7980000000001
end program

记录中 (Logging)

Another common use for decorator is to log the use of the functions.

装饰器的另一个常用用法是记录功能的使用。

打回来 (Callback)

A callback function is a function called when a certain event occurs, like a route has been called, a message received, or a server has done processing.

回调函数是在特定事件发生时调用的函数,例如已调用路由,收到消息或服务器已完成处理。

You can then add a function to be executed when this event have occurred. For example, this is used in HTTP servers to response to a URL request.

然后,您可以添加此事件发生后要执行的功能。 例如,在HTTP服务器中使用它来响应URL请求。

检查条件 (Check conditions)

You can use a decorator to check a condition before executing a function, such as if the user is logged in, if it has permissions to use it, or even if the arguments are valid ones (types, values, etc).

您可以在执行功能之前使用修饰符检查条件,例如用户是否已登录,用户是否有权使用它,或者参数是否为有效的参数(类型,值等)。

Output:

输出:

start program
Traceback (most recent call last):
File "example_permission.py", line 22, in <module>
do_something()
File "example_permission.py", line 7, in wrapped_check
raise ValueError("Not permitted")
ValueError: Not permitted

创建单例 (Creating singleton)

You can use a decorator to decorate a class. The only difference is that the decorator receives a class instead of a function.

您可以使用装饰器来装饰类。 唯一的区别是装饰器接收的是类而不是函数。

A singleton is a class with only one instance. We can save the instance as an attribute of the wrapper function and return it when requested. It is useful when we are dealing with database connections, for example.

单例是只有一个实例的类。 我们可以将实例另存为包装函数的属性,并在请求时返回它。 例如,当我们处理数据库连接时,它很有用。

Output:

输出:

start
140548309536336
140548309536336
end

错误处理 (Error handling)

You can make sure that some family of exceptions are handled, without have to enter a try block for each function you need to check it. Then you can log or stop the execution of the program.

您可以确保处理了一些异常,而不必为需要检查它的每个函数输入try块。 然后,您可以记录或停止程序的执行。

Output:

输出:

start
5.0
>> Error in func div
0
end

结论 (Conclusion)

In this article we have seen about Python decorators and their uses. It is a nice tool to improve your code and make your project easier to use and maintain.

在本文中,我们了解了Python装饰器及其用法。 这是一个很好的工具,可以改善您的代码并使项目更易于使用和维护。

Some of their properties:

它们的一些特性:

  • They can be reused.

    它们可以重复使用。
  • They can receive parameters and return values.

    他们可以接收参数并返回值。
  • They can store values.

    他们可以存储值。
  • They can decorate classes.

    他们可以装饰类。
  • They can add functionality to other functions and classes.

    他们可以将功能添加到其他功能和类。

Python has also some builtin decorators like classmethod, property and staticmethod.

Python还有一些内置的装饰器,例如classmethodpropertystaticmethod

You can use decorators with other methods, such as dunder methods, to enrich your classes and project.

您可以将装饰器与其他方法(例如dunder方法)一起使用,以丰富您的类和项目。

升级编码 (Level Up Coding)

Thanks for being a part of our community! Subscribe to our YouTube channel or join the Skilled.dev coding interview course.

感谢您加入我们的社区! 订阅我们的YouTube频道或参加Skilled.dev编码面试课程

翻译自: https://levelup.gitconnected.com/a-guide-to-python-decorators-f3b03dd05514

python 装饰器装饰类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值