IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 如何在 Python 中创建和使用装饰器(含示例) -> 正文阅读

[Python知识库]如何在 Python 中创建和使用装饰器(含示例)

如何在 Python 中创建和使用装饰器(含示例)

?

Python 装饰器允许你在不修改函数本身的情况下更改函数的行为。

在本文中,我将向你展示如何创建和使用装饰器。你将看到使用这个高级的 Python 功能是多么容易。

在本文中,我将讨论以下主题:

  • 何时在 Python 中使用装饰器
  • 用于创建装饰器的构建块
  • 如何创建一个 Python 装饰器
  • Python 装饰器的真实示例
  • Python 中的类装饰器

何时在 Python 中使用装饰器

当你需要更改函数的行为而不修改函数本身时,你将使用装饰器,比如当你想要添加日志记录、测试性能、执行缓存、验证权限等时。

当你需要在多个函数上运行相同的代码时,也可以使用装饰器。这可以避免你编写重复的代码。

以下是用于创建 Python 装饰器的构建块

为了更好地理解装饰器的工作原理,你应该先了解一些概念。

  1. 函数是一个对象。因此,可以将函数分配给变量,可以从该变量访问该函数。
def my_function():

    print('I am a function.')

# Assign the function to a variable without parenthesis. We don't want to execute the function.

description = my_function
# Accessing the function from the variable I assigned it to.

print(description())

# Output

'I am a function.'

2. 一个函数可以嵌套在另一个函数中。

def outer_function():

    def inner_function():

        print('I came from the inner function.')

    # Executing the inner function inside the outer function.
    inner_function()
outer_function()

# Output

I came from the inner function.

请注意,inner_function?在?outer_function?之外不可用。如果我尝试在?outer_function?之外执行?inner_function,则会收到 NameError 异常。

inner_function()

Traceback (most recent call last):
  File "/tmp/my_script.py", line 9, in <module>
    inner_function()
NameError: name 'inner_function' is not defined

3. 由于一个函数可以嵌套在另一个函数中,所以它也可以被返回。

def outer_function():
    '''Assign task to student'''

    task = 'Read Python book chapter 3.'
    def inner_function():
        print(task)
    return inner_function

homework = outer_function()
homework()

# Output

'Read Python book chapter 5.'

4. 一个函数可以作为参数传递给另一个函数。

def friendly_reminder(func):
    '''Reminder for husband'''

    func()
    print('Don\'t forget to bring your wallet!')

def action():

    print('I am going to the store buy you something nice.')
# Calling the friendly_reminder function with the action function used as an argument.

friendly_reminder(action)

# Output

I am going to the store buy you something nice.
Don't forget to bring your wallet!

如何创建一个 Python 装饰器

为了在 Python 中创建装饰器函数,我创建了一个将函数作为参数的外部函数,还有一个内部函数包含装饰函数。

以下是基本的 Python 装饰器的语法:

def my_decorator_func(func):

    def wrapper_func():
        # Do something before the function.
        func()
        # Do something after the function.
    return wrapper_func

要使用装饰器,你可以将其附加到一个函数,就像你在下面的代码中看到的那样。我们通过将装饰器的名称直接放在我们想要使用它的函数上方来使用装饰器。使用?@?符号作为装饰器函数的前缀。

@my_decorator_func
def my_func():

    pass

这是一个简单的例子。此装饰器记录执行函数的日期和时间:

from datetime import datetime


def log_datetime(func):
    '''Log the date and time of a function'''

    def wrapper():
        print(f'Function: {func.__name__}\nRun on: {datetime.today().strftime("%Y-%m-%d %H:%M:%S")}')
        print(f'{"-"*30}')
        func()
    return wrapper


@log_datetime
def daily_backup():

    print('Daily backup job has finished.')   

     
daily_backup()

# Output

Daily backup job has finished.
Function: daily_backup
Run on: 2021-06-06 06:54:14
---------------------------

如何在 Python 中为装饰器添加参数

可以将参数传递给装饰器。为了给装饰器添加参数,我将?*args??**kwargs?添加到内部函数中。

  • *args?将采用任意类型的无限数量的参数,例如?10True?或?'Brandon'
  • **kwargs?将采用无限数量的关键字参数,例如?count=99is_authenticated=True?或?name='Brandon'

这是一个带参数的装饰器:

def my_decorator_func(func):

    def wrapper_func(*args, **kwargs):
        # Do something before the function.
        func(*args, **kwargs)
        # Do something after the function.
    return wrapper_func


@my_decorator_func
def my_func(my_arg):
    '''Example docstring for function'''

    pass

装饰器隐藏正在装饰的函数。如果我检查?__name__?或?__doc__?方法,我们会得到一个意想不到的结果。

print(my_func.__name__)
print(my_func.__doc__)

# Output

wrapper_func
None

为了解决这个问题,我将使用?functools,它将使用装饰函数属性更新装饰器。

from functools import wraps

def my_decorator_func(func):

    @wraps(func)
    def wrapper_func(*args, **kwargs):
        func(*args, **kwargs)
    return wrapper_func

@my_decorator_func
def my_func(my_args):
    '''Example docstring for function'''

    pass

现在我得到了我期待的输出。

print(my_func.__name__)
print(my_func.__doc__)

# Output

my_func
Example docstring for function

运行中的 Python 装饰器示例

我创建了一个装饰器来测量函数的内存和速度。我们将使用装饰器来测试性能列表生成,使用四种方法:范围、列表、追加和连接。

from functools import wraps
import tracemalloc
from time import perf_counter 


def measure_performance(func):
    '''Measure performance of a function'''

    @wraps(func)
    def wrapper(*args, **kwargs):
        tracemalloc.start()
        start_time = perf_counter()
        func(*args, **kwargs)
        current, peak = tracemalloc.get_traced_memory()
        finish_time = perf_counter()
        print(f'Function: {func.__name__}')
        print(f'Method: {func.__doc__}')
        print(f'Memory usage:\t\t {current / 10**6:.6f} MB \n'
              f'Peak memory usage:\t {peak / 10**6:.6f} MB ')
        print(f'Time elapsed is seconds: {finish_time - start_time:.6f}')
        print(f'{"-"*40}')
        tracemalloc.stop()
    return wrapper


@measure_performance
def make_list1():
    '''Range'''

    my_list = list(range(100000))


@measure_performance
def make_list2():
    '''List comprehension'''

    my_list = [l for l in range(100000)]


@measure_performance
def make_list3():
    '''Append'''

    my_list = []
    for item in range(100000):
        my_list.append(item)


@measure_performance
def make_list4():
    '''Concatenation'''

    my_list = []
    for item in range(100000):
        my_list = my_list + [item]


make_list1()
make_list2()
make_list3()
make_list4()

# Output

Function: make_list1
Method: Range
Memory usage:		        0.000072 MB 
Peak memory usage:	        3.693040 MB 
Time elapsed is seconds:    0.049359
----------------------------------------

Function: make_list2
Method: List comprehension
Memory usage:		        0.000856 MB 
Peak memory usage:	        3.618244 MB 
Time elapsed is seconds:    0.052338
----------------------------------------

Function: make_list3
Method: Append
Memory usage:		        0.000448 MB 
Peak memory usage:	        3.617692 MB 
Time elapsed is seconds:    0.060719
----------------------------------------

Function: make_list4
Method: Concatenation
Memory usage:		        0.000440 MB 
Peak memory usage:	        4.393292 MB 
Time elapsed is seconds:    61.649138
----------------------------------------

你也可以将装饰器与类一起使用。让我们看看如何在 Python 类中使用装饰器。

在此示例中,请注意不涉及?@?字符。使用?__call__?方法,装饰器在创建类的实例时执行。

这个类跟踪查询 API 的函数已运行的次数。一旦达到限制,装饰器就会停止执行该函数。

import requests


class LimitQuery:

    def __init__(self, func):
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.limit = args[0]
        if self.count < self.limit:
            self.count += 1
            return self.func(*args, **kwargs)
        else:
            print(f'No queries left. All {self.count} used.')
            return

@LimitQuery
import requests

def get_coin_price():
    '''View the Bitcoin Price Index (BPI)'''
    
    url = requests.get('https://api.coindesk.com/v1/bpi/currentprice.json')

    if url.status_code == 200:
        text = url.json()
        return f"${float(text['bpi']['USD']['rate_float']):.2f}")


get_coin_price(5)
get_coin_price(5)
get_coin_price(5)
get_coin_price(5)
get_coin_price(5)

# Output

$35968.25
$35896.55
$35368.14
$35962.27
No queries left. All 5 used.

这个类将跟踪类的状态。

结语

如果对Python有兴趣,想了解更多的Python以及AIoT知识,解决测试问题,以及入门指导,帮你解决学习Python中遇到的困惑,我们这里有技术高手。如果你正在找工作或者刚刚学校出来,又或者已经工作但是经常觉得难点很多,觉得自己Python方面学的不够精想要继续学习的,想转行怕学不会的, 都可以加入我们,可领取最新Python大厂面试资料和Python爬虫、人工智能、学习资料!VX【pydby01】暗号CSDN

?

在这篇文章中,我谈到了如何将函数传递给变量、嵌套函数、返回函数以及将函数作为参数传递给另一个函数。

我还向你展示了如何创建和使用 Python 装饰器以及一些实际示例。希望你现在能够在你的项目中添加装饰器了。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:37:39  更:2021-12-16 17:40:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 5:48:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码