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…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
