Python一分钟:装饰器
一、装饰器基础
函数即对象
在python中函数可以作为参数传递,和任何其它对象一样如:str、int、float、list等等
def say_hello(name):return f"Hello {name}"def be_awesome(name):return f"Yo {name}, together we're the awesomest!"def greet_bob(greeter_func):return greeter_func("Bob")
内部函数
在函数内部可以创建函数,这样的函数被称为内部函数:
def parent():print("Printing from parent()")def first_child():print("Printing from first_child()")def second_child():print("Printing from second_child()")second_child()first_child()
在python在交互式shell中运行:
python -i test.py
在使用 Python 时,尤其是在交互式 shell 中,其强大的自省(introspection)能力提供了极大的便利。自省是指对象在运行时能够了解自身属性的能力。
>>> parent()
内部函数只有在父函数被调用时才会被定义,它的作用域仅限于父函数parent()内:
>>> first_child()
Traceback (most recent call last):...
NameError: name 'first_child' is not defined
函数作为返回值
函数可以作为返回值返回:
def parent(num):def first_child():return "Hi, I'm Elias"def second_child():return "Call me Ester"if num == 1:return first_childelse:return second_child
通过变量保存返回的函数引用,可以像普通函数那样正常调用:
>>> first = parent(1)
>>> second = parent(2)>>> first
<function parent.<locals>.first_child at 0x7f599f1e2e18>>>> second
<function parent.<locals>.second_child at 0x7f599dad5268>
简单的装饰器
def decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapperdef say_whee():print("Whee!")say_whee = decorator(say_whee)
在shell中运行:
>>> from hello_decorator import say_whee>>> say_whee()
# <function decorator.<locals>.wrapper at 0x7f3c5dfd42f0>
通过@符号来使用装饰器:
def decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@decorator
def say_whee():print("Whee!")
传递参数:
def do_twice(func):def wrapper_do_twice(*args, **kwargs):func(*args, **kwargs)func(*args, **kwargs)return wrapper_do_twice
在shell中运行:
>>> from decorators import do_twice>>> @do_twice
... def return_greeting(name):
... print("Creating greeting")
... return f"Hi {name}"
...>>> return_greeting("Adam")
# Creating greeting
# Creating greeting
# 'Hi Adam'
保留原始信息
当函数被我们之前创建的装饰器装饰时,它的内部信息就会变得混乱,使用@functools.wraps装饰器可以解决这个问题:
import functoolsdef do_twice(func):@functools.wraps(func)def wrapper_do_twice(*args, **kwargs):func(*args, **kwargs)return func(*args, **kwargs)return wrapper_do_twice
在shell中运行:
>>> from decorators import do_twice>>> @do_twice
... def say_whee():
... print("Whee!")
...>>> say_whee
<function say_whee at 0x7ff79a60f2f0>>>> say_whee.__name__
'say_whee'>>> help(say_whee)
Help on function say_whee in module whee:say_whee()
可以看到经过@functools.wraps装饰器后,say_whee函数的元数据被保留下来,包括函数名、文档字符串等。
二、更复杂的装饰器
嵌套装饰器
装饰器可以堆叠用于一个函数:
>>> from decorators import debug, do_twice>>> @debug
... @do_twice
... def greet(name):
... print(f"Hello {name}")
带参数的装饰器
我们可以定义能够接收参数的装饰器,如下:
from decorators import repeat@repeat(num_times=4)
def greet(name):print(f"Hello {name}")greet("World")
实现方法如下:
import functools# ...def repeat(num_times):def decorator_repeat(func):@functools.wraps(func)def wrapper_repeat(*args, **kwargs):for _ in range(num_times):value = func(*args, **kwargs)return valuereturn wrapper_repeatreturn decorator_repeat
拆分讲解上面的代码:
首先decorator_repeat部分的行为,就和我们之前定义的普通装饰器一样:
...def decorator_repeat(func):@functools.wraps(func)def wrapper_repeat(*args, **kwargs):for _ in range(num_times):value = func(*args, **kwargs)return valuereturn wrapper_repeat
...
外层由repeat()函数接收参数,并返回wrapper_repeat装饰器的引用。
在装饰器中跟踪状态
可以实现装饰器对象中添加属性来追踪函数调用次数:
import functoolsdef count(func):@functools.wraps(func)def warp(*args, **kwargs):warp.num_calls += 1print(f"Call {warp.num_calls} of {func.__name__}()")return func(*args, **kwargs)warp.num_calls = 0return warp@count
def hello():print("Hello")hello()
hello()
hello()
类装饰器
有两种不同的方式可以在类中使用装饰器,第一种方法和我们上面学到的在函数中使用装饰器的方法非常类似。
Python有很多内置的装饰器很常用:
@classmethod@staticmethod@property
在python中维护状态的典型方法就是使用类。之前实现的count函数可以使用类装饰器重写。为了使实例可调用,需要实现.__call__()方法:
>>> class Counter:
... def __init__(self, start=0):
... self.count = start
... def __call__(self):
... self.count += 1
... print(f"Current count is {self.count}")
每次调用实例都会执行.__call__()方法:
>>> counter = Counter()
>>> counter()
Current count is 1>>> counter()
Current count is 2>>> counter.count
实现装饰器类的典型方法是应该实现.__init__()和.__call__()
import functools# ...class CountCalls:def __init__(self, func):functools.update_wrapper(self, func)self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"Call {self.num_calls} of {self.func.__name__}()")return self.func(*args, **kwargs)
使用方法:
>>> from decorators import CountCalls>>> @CountCalls
... def say_whee():
... print("Whee!")
...>>> say_whee()
# Call 1 of say_whee()
# Whee!>>> say_whee()
# Call 2 of say_whee()
# Whee!>>> say_whee.num_calls
# 2
原文链接
相关文章:
Python一分钟:装饰器
一、装饰器基础 函数即对象 在python中函数可以作为参数传递,和任何其它对象一样如:str、int、float、list等等 def say_hello(name):return f"Hello {name}"def be_awesome(name):return f"Yo {name}, together were the awesomest!"def gr…...
Docker部署ddns-go教程(包含完整的配置过程)
本章教程教程,主要介绍如何用Docker部署ddns-go。 一、拉取容器 docker pull jeessy/ddns-go:v6.7.0二、运行容器 docker run -d \--name ddns-go \--restart unless-stopped \...
简单多状态dp第三弹 leetcode -买卖股票的最佳时机问题
309. 买卖股票的最佳时机含冷冻期 买卖股票的最佳时机含冷冻期 分析: 使用动态规划解决 状态表示: 由于有「买入」「可交易」「冷冻期」三个状态,因此我们可以选择用三个数组,其中: ▪ dp[i][0] 表示:第 i 天结束后,…...
游戏化在电子课程中的作用:提高参与度和学习成果
游戏化,即游戏设计元素在非游戏环境中的应用,已成为电子学习领域的强大工具。通过将积分、徽章、排行榜和挑战等游戏机制整合到教育内容中,电子课程可以变得更具吸引力、激励性和有效性。以下是游戏化如何在转变电子学习中发挥重要作用&#…...
php+mysql安装
1.卸载mysql 没启动不停止 2.下载 3.解压 4.点击安装 5.出现成功 端口占用修改 修改端口89或者87 可视化扩展 修改后重启 开启扩展...
音视频入门基础:FLV专题(5)——FFmpeg源码中,判断某文件是否为FLV文件的实现
一、引言 通过FFmpeg命令: ./ffmpeg -i XXX.flv 可以判断出某个文件是否为FLV文件: 所以FFmpeg是怎样判断出某个文件是否为FLV文件呢?它内部其实是通过flv_probe函数来判断的。从《FFmpeg源码:av_probe_input_format3函数和AVI…...
Tomcat 乱码问题彻底解决
1. 终端乱码问题 找到 tomcat 安装目录下的 conf ---> logging.properties .修改ConsoleHandler.endcoding GBK (如果在idea中设置了UTF-8字符集,这里就不需要修改) 2. CMD命令窗口设置编码 参考:WIN10的cmd查看编码方式&am…...
RGB颜色模型
RGB颜色模型是一种广泛应用于数字图像和计算机图形领域的颜色表示方法 一、基本概念 RGB 代表红色(Red)、绿色(Green)和蓝色(Blue)三种基本颜色。这些颜色被视为加色模型中的原色,意味着它们可…...
智能工厂的软件设计 创新型原始制造商(“创新工厂“)的Creator原型(统一行为理论)之2
Q8、今天我们继续昨天开始的 “智能工厂的软件设计”以“统一行为理论”为指导原则的 创新型原始制造商的Creator伪代码--创新工厂“原型”。这是在前述将“程序program”问题的三个体现“方面”(逻辑/语言/数学) 视为符号学的三分支(语用语义…...
【个人博客hexo版】hexo安装时会出现的一些问题
项目场景: 项目场景:在完成了GitHub仓库和git的连接之后,就要新建一个文件夹(例如hexo blog)进行下一步hexo的使用 问题描述 例如:如图所示 原因分析: 这些error不用看它到底是什么…...
道路裂缝,坑洼,病害数据集-包括无人机视角,摩托车视角,车辆视角覆盖道路
道路裂缝,坑洼,病害数据集 包括无人机视角,摩托车视角,车辆视角 覆盖道路所有问题 一共有八类16000张 1到7依次为: [横向裂缝, 纵向裂缝, 块状裂缝, 龟裂, 坑槽, 修补网状裂缝, 修补裂缝, 修补坑槽] 道路病害(如裂缝、…...
java接口文档配置
接口文档配置 一. swagger与knife4j 配置 1. 导入依赖 <!--swagger接口文档说明--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId> </dependency> <dependency><groupId>…...
【服务器第二期】mobaxterm软件下载及连接
【服务器第二期】mobaxterm软件下载及连接 前言什么是SSH什么是FTP/SFTP mobaxterm软件介绍mobaxterm软件下载SSH登录使用方法1-新建ssh连接方法2-打开已有的ssh连接方法3-通过ssh命令建立连接 SFTP数据传输方法1-建立ssh连接后直接拖拽方法2-建立sftp连接再拖拽方法3-直接使用…...
排序-----计数排序(非比较排序)
原理: 存在的问题:数组空间浪费 所以要相对映射,不要绝对映射 calloc()函数的功能是:为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0. // 时间复杂度:O(Nrange) // 只适合整数/适合范围集中 // 空间范围度:…...
[Python]案例驱动最佳入门:Python数据可视化在气候研究中的应用
在全球气候问题日益受到关注的今天,气温变化成为了科学家、政府、公众讨论的热门话题。然而,全球气温究竟是如何变化的?我们能通过数据洞察到哪些趋势?本文将通过真实模拟的气温数据,结合Python数据分析和可视化技术&a…...
PyQt5 导入ui文件报错 AttributeError: type object ‘Qt‘ has no attribute
问题描述: 利用 PyQt5 编写可视化界面是较为普遍的做法,但是使用全新UI版本的 Pycharm 修改之前正常的UI文件时,在没有动其他代码的情况下发现出现以下报错 AttributeError: type object Qt has no attribute Qt::ContextMenuPolicy::Defaul…...
Unity中Rigidbody 刚体组件和Rigidbody类是什么?
Rigidbody 刚体组件 Rigidbody 是 Unity 中的一个组件,它可以让你的游戏对象像真实世界中的物体一样移动和碰撞。想象一下,你有一个小球,你希望它像真实世界中的球一样滚动、弹跳和碰撞,那么你就可以给这个小球添加一个 Rigidbod…...
MySQL学习笔记(持续更新中)
1、Mysql概述 1.1 数据库相关概念 三个概念:数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库,数据是有组织的进行存储DataBase(DB)数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System…...
sqlserver插入数据删除数据
1、插入数据 1.1 直接插入 1.1.1 方式一 insert into test values(001,黎明,1),(002,冯绍峰,1),(003,菲菲,2);1.1.2 方式二 insert into test(ID,Name,Sex) values(004,丽丽,2),(005,凌晨,2),(006,虾米,1);1.2 插入部分行 insert into test(ID,Name) values(007,红)2、删除…...
[51单片机] 简单介绍 (一)
文章目录 1.单片机介绍2.单片机内部三大资源3.单片机最小系统4.STC89C52单片机 1.单片机介绍 兼容Intel的MCS-51体系架构的一系列单片机。 STC89C52:8K FLASH、512字节RAM、32个IO口、3个定时器、1个UART、8个中断源。 单片机简称MCU单片机内部集成了CPU、RAM、RO…...
PN5180 ISO15693协议栈实现与嵌入式NFC开发指南
1. PN5180库深度解析:面向嵌入式工程师的NFC ISO15693协议栈实现指南NXP PN5180是业界领先的多协议NFC控制器,支持ISO/IEC 14443 A/B、ISO/IEC 15693、Felica及NFC Forum Type 1–5标签。其核心优势在于高集成度射频前端、可编程调制解调器及灵活的主机接…...
StructuredTaskScope配置不生效?揭秘ClassLoader隔离、虚拟线程绑定与作用域传播的3层断点排查法
第一章:StructuredTaskScope配置不生效?揭秘ClassLoader隔离、虚拟线程绑定与作用域传播的3层断点排查法当使用 Java 21 的 StructuredTaskScope 时,常见现象是:明明调用了 scope.fork() 并设置了自定义上下文(如 MDC、…...
Overleaf-Workshop:在VSCode中实现Open Overleaf项目的无缝协作与高效管理
Overleaf-Workshop:在VSCode中实现Open Overleaf项目的无缝协作与高效管理 【免费下载链接】Overleaf-Workshop Open Overleaf/ShareLaTex projects in vscode, with full collaboration support. 项目地址: https://gitcode.com/gh_mirrors/ov/Overleaf-Workshop…...
Ansible Playbook在JumpServer中的高级用法:自动化运维效率提升技巧
Ansible Playbook在JumpServer中的高阶实战:效率倍增的自动化运维策略 开篇:当堡垒机遇上自动化运维 想象一下这样的场景:凌晨三点,服务器突然告警,传统运维需要手动登录每台机器检查状态,而熟练使用Ansibl…...
别再为MoveIt安装发愁了!Ubuntu 20.04 + ROS Noetic 保姆级配置全流程
别再为MoveIt安装发愁了!Ubuntu 20.04 ROS Noetic 保姆级配置全流程 刚接触ROS和机械臂控制时,MoveIt的安装过程就像一道难以逾越的门槛。记得我第一次尝试配置时,整整两天都卡在依赖报错和环境变量设置上。本文将带你用最稳妥的方式&#x…...
SAR成像系列:【10】合成孔径雷达(SAR)波数域(omega-K)算法实战:从理论到Matlab实现
1. 波数域算法:为什么它是SAR成像的"瑞士军刀"? 第一次接触omega-K算法时,我被它优雅的数学表达和精确的成像效果震撼到了。这种算法在业内有个更直白的名字——距离徙动算法(Range Migration Algorithm)&am…...
无需配置环境!MinerU镜像一键部署,即刻体验智能文档解析
无需配置环境!MinerU镜像一键部署,即刻体验智能文档解析 1. 为什么选择智能文档解析? 在日常办公和学习中,我们经常需要处理各种文档资料:PDF报告、扫描合同、学术论文、财务报表等。传统方式要么需要手动输入&#…...
基于STM32H743的调试记录2——从CubeMX到MDK:构建现代化工程模板的实战指南
1. 为什么需要现代化工程模板 最近在折腾STM32H743的时候,发现一个很有意思的现象:很多开发者还在使用几年前的老旧工程模板。我自己刚开始用某原子的开发板学习时也踩过这个坑,板子配套的例程跑起来没问题,但一旦想实现些复杂功…...
OFA图像描述模型效果展示:多类型图片生成描述案例分享
OFA图像描述模型效果展示:多类型图片生成描述案例分享 1. 引言:OFA模型的独特价值 在当今视觉内容爆炸式增长的时代,能够自动理解并描述图像内容的技术变得越来越重要。OFA(One For All)图像描述模型正是为解决这一需…...
Node Binance Trader回测功能实战指南:从历史数据到盈利策略
Node Binance Trader回测功能实战指南:从历史数据到盈利策略 【免费下载链接】node-binance-trader 💰 Cryptocurrency Trading Strategy & Portfolio Management Development Framework for Binance. 🤖 项目地址: https://gitcode.co…...
