当前位置: 首页 > news >正文

Python 装饰模式

在软件开发中,随着系统的复杂性增加,需求的变化往往会导致代码的频繁修改。为了提高代码的灵活性和可维护性,设计模式应运而生。其中,装饰模式(Decorator Pattern)是一种非常实用的结构型设计模式,它允许在不改变对象自身的情况下,动态地给对象添加额外的功能。

1. 什么是装饰模式?

装饰模式是一种设计模式,它通过将对象包装在一个装饰器类中来实现功能的扩展。装饰器类可以在调用原始对象的方法之前或之后添加额外的行为。这种方式使得我们可以在运行时动态地改变对象的行为,而不需要修改对象的代码。
装饰模式的核心思想是“将功能分离”。通过将功能封装在不同的装饰器中,我们可以灵活地组合这些装饰器,从而实现复杂的功能。这种方式不仅提高了代码的复用性,还使得系统的扩展变得更加简单。

1.2 装饰模式的组成部分

1.2.1 组件接口(Component)

  • 定义:组件接口是装饰模式的核心,它定义了被装饰对象和装饰器的共同接口。这个接口通常包含一个或多个方法,供具体组件和装饰器实现。
  • 作用:通过定义统一的接口,装饰模式可以在不改变具体组件的情况下,动态地添加或修改功能。
class Coffee:def cost(self):raise NotImplementedError("You should implement this method!")

1.2.2 具体组件(Concrete Component)

  • 定义:具体组件是实现组件接口的类,表示需要被装饰的对象。具体组件包含了基本的功能实现。
  • 作用:具体组件提供了装饰模式的基础功能,装饰器将在此基础上添加额外的功能。
class SimpleCoffee(Coffee):def cost(self):return 5  # 基础咖啡的价格

1.2.3. 装饰器(Decorator)

  • 定义:装饰器也是实现组件接口的类,持有一个组件对象的引用,并在其方法中调用该组件的方法。装饰器可以在调用组件的方法之前或之后添加额外的功能。
  • 作用:装饰器提供了一个包装层,使得可以在不修改具体组件的情况下,动态地添加功能。
class CoffeeDecorator(Coffee):def __init__(self, coffee):self._coffee = coffee  # 持有一个组件对象的引用def cost(self):return self._coffee.cost()  # 调用被装饰的对象的方法

1.2.4 具体装饰器(Concrete Decorator)

  • 定义:具体装饰器继承自装饰器类,添加具体的功能或行为。每个具体装饰器可以实现不同的功能,从而为组件提供多种扩展方式。
  • 作用:具体装饰器实现了额外的功能,可以在调用组件的方法时添加新的行为。
class MilkDecorator(CoffeeDecorator):def cost(self):return self._coffee.cost() + 1  # 添加牛奶的额外费用class SugarDecorator(CoffeeDecorator):def cost(self):return self._coffee.cost() + 0.5  # 添加糖的额外费用

1.2.5 使用示例

# 创建一个基础咖啡
coffee = SimpleCoffee()
print("Cost of simple coffee:", coffee.cost())  # 输出: Cost of simple coffee: 5# 添加牛奶装饰
milk_coffee = MilkDecorator(coffee)
print("Cost of coffee with milk:", milk_coffee.cost())  # 输出: Cost of coffee with milk: 6# 添加糖装饰
sugar_milk_coffee = SugarDecorator(milk_coffee)
print("Cost of coffee with milk and sugar:", sugar_milk_coffee.cost())  # 输出: Cost of coffee with milk and sugar: 6.5

1.3 装饰模式的优点

  • 灵活性:装饰模式允许在运行时动态地添加或修改对象的行为,而不需要修改对象的代码。这种灵活性使得系统能够快速适应变化的需求。

  • 单一职责原则:通过将功能分散到多个装饰器中,可以使每个装饰器只负责特定的功能,符合单一职责原则。这种设计使得代码更加清晰,易于维护。

  • 可扩展性:装饰模式允许通过组合不同的装饰器来创建复杂的功能,而不需要创建大量的子类。这种方式使得系统的扩展变得简单,减少了代码的重复。

2. Python 装饰器

装饰器是 Python 中一种强大的功能,它允许您在不修改原始函数代码的情况下增强或修改函数的行为。装饰器通过将额外的功能封装在一个函数中,使得可以在运行时动态地改变对象的行为。

2.1 什么是装饰器?

在 Python 中,装饰器是一种特殊的函数,用于在运行时动态地修改或增强其他函数或方法的功能。装饰器通常用于以下场景:

  • 记录日志
  • 访问控制和权限检查
  • 缓存或记忆化
  • 计时和性能监控

装饰器的基本语法使用 @decorator_name 的形式,放在被装饰函数的定义之前。

2.2 装饰器的基本结构

装饰器通常是一个接受函数作为参数并返回一个新函数的高阶函数。下面是装饰器的一般结构:

def my_decorator(func):def wrapper(*args, **kwargs):# 在调用原函数之前执行的代码result = func(*args, **kwargs)  # 调用原函数# 在调用原函数之后执行的代码return resultreturn wrapper

2.3 简单的装饰器

下面是一个简单的装饰器示例,它在函数执行前后打印一些信息。

def my_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@my_decorator
def say_hello():print("Hello!")# 调用装饰后的函数
say_hello()

输出:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

解释:

  • my_decorator 是一个装饰器,它接受一个函数 func 作为参数。
  • wrapper 是一个内部函数,它在调用 func 之前和之后执行一些操作。
  • 使用 @my_decorator 语法将 say_hello 函数装饰为 wrapper 函数。

2.4 带参数的装饰器

带参数的装饰器允许您在装饰器中使用参数,以便根据这些参数改变装饰的行为。

def repeat(num_times):"""一个装饰器,用于重复执行函数指定的次数"""def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):result = func(*args, **kwargs)  # 调用被装饰的函数return result  # 返回最后一次调用的结果return wrapperreturn decorator_repeat@repeat(3)  # 指定重复执行3次
def greet(name):"""打印问候信息"""print(f"Hello, {name}!")# 调用装饰后的函数
greet("Alice")

输出:

Hello, Alice!
Hello, Alice!
Hello, Alice!

解释:

  • repeat(num_times) 是一个带参数的装饰器,它接受一个参数 num_times,表示函数需要被重复执行的次数。
  • decorator_repeat(func) 是实际的装饰器,它接受被装饰的函数。
  • wrapper 函数在调用原始函数 func 时重复执行指定的次数。

2.5 使用 functools.wraps

使用装饰器时,原始函数的元数据(如名称和文档字符串)会被覆盖。为了保留这些信息,可以使用 functools.wraps 装饰器。

import functoolsdef my_decorator_with_wraps(func):@functools.wraps(func)  # 保留原始函数的元数据def wrapper(*args, **kwargs):print("Before calling the function.")result = func(*args, **kwargs)print("After calling the function.")return resultreturn wrapper@my_decorator_with_wraps
def say_goodbye():"""This function says goodbye."""print("Goodbye!")# 调用装饰后的函数
say_goodbye()# 查看函数的元数据
print(say_goodbye.__name__)  # 输出: say_goodbye
print(say_goodbye.__doc__)   # 输出: This function says goodbye.

输出:

Before calling the function.
Goodbye!
After calling the function.
say_goodbye
This function says goodbye.

解释:

  • wrapper 函数上使用 @functools.wraps(func),这样可以保留原始函数的名称和文档字符串。
  • 调用 say_goodbye.__name__say_goodbye.__doc__ 可以验证元数据是否被保留。

2.6 装饰器链

多个装饰器可以叠加在一个函数上,形成装饰器链。

def decorator_one(func):def wrapper(*args, **kwargs):print("Decorator One: Before function call")result = func(*args, **kwargs)print("Decorator One: After function call")return resultreturn wrapperdef decorator_two(func):def wrapper(*args, **kwargs):print("Decorator Two: Before function call")result = func(*args, **kwargs)print("Decorator Two: After function call")return resultreturn wrapper@decorator_one
@decorator_two
def say_hello():print("Hello!")# 调用装饰后的函数
say_hello()

输出:

Decorator One: Before function call
Decorator Two: Before function call
Hello!
Decorator Two: After function call
Decorator One: After function call

解释:

  • 在这个例子中,say_hello 函数被两个装饰器 decorator_onedecorator_two 装饰。
  • 调用 say_hello() 时,装饰器的执行顺序是从内到外(即 decorator_two 先执行,然后是 decorator_one)。

3. 例子 1:在线购物系统

创建一个简单的在线购物系统,用户可以添加商品到购物车、结算并查看订单。我们将使用装饰器来实现以下功能:

  1. 输入验证:确保用户输入的商品数量是有效的。
  2. 日志记录:记录用户的操作日志。
  3. 性能监控:监控结算操作的执行时间。
import time
from functools import wraps# 输入验证
def validate_quantity(func):@wraps(func)def wrapper(*args, **kwargs):quantity = args[3] if len(args) >= 4 else kwargs.get('quantity', 0)if quantity <= 0:return "Error: Quantity must be greater than zero."return func(*args, **kwargs)return wrapper# 日志记录
def log_action(func):@wraps(func)def wrapper(*args, **kwargs):user = args[1]print(f"User {user} is performing an action.")result = func(*args, **kwargs)print(f"User {user} completed the action.")return resultreturn wrapper# 性能监控
def performance_monitor(func):@wraps(func)def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"Execution time for {func.__name__}: {end_time - start_time:.4f} seconds")return resultreturn wrapper# 商品类
class Product:def __init__(self, name, price):self.name = nameself.price = price# 购物车类
class ShoppingCart:def __init__(self):self.items = {}@log_action  # 调整装饰器顺序,先记录日志再验证@validate_quantitydef add_item(self, user, product, quantity):if product in self.items:self.items[product] += quantityelse:self.items[product] = quantityreturn f"Added {quantity} of {product.name} to the cart."@performance_monitor@log_actiondef checkout(self, user):time.sleep(1)total_cost = sum(product.price * quantity for product, quantity in self.items.items())self.items.clear()return f"Checkout successful! Total cost: ${total_cost:.2f}"# 使用示例
if __name__ == "__main__":product1 = Product("Laptop", 1000)product2 = Product("Headphones", 100)cart = ShoppingCart()user = "Alice"print(cart.add_item(user, product1, 1))  # 正常添加print(cart.add_item(user, product2, 2))  # 正常添加print(cart.add_item(user, product2, -1))  # 无效数量print(cart.checkout(user))  # 结算
User Alice is performing an action.
User Alice completed the action.
Added 1 of Laptop to the cart.
User Alice is performing an action.
User Alice completed the action.
Added 2 of Headphones to the cart.
User Alice is performing an action.
User Alice completed the action.
Error: Quantity must be greater than zero.
User Alice is performing an action.
User Alice completed the action.
Execution time for checkout: 1.0052 seconds
Checkout successful! Total cost: $1200.00
  1. 输入验证
    • validate_quantity 装饰器确保用户输入的商品数量大于零。如果数量无效,返回错误信息。
  2. 日志记录
    • log_action 装饰器在用户执行操作时记录日志,显示用户的操作开始和结束。
  3. 性能监控
    • performance_monitor 装饰器监控结算操作的执行时间,并在控制台输出执行时长。

优点

  • 灵活性:通过装饰器,我们可以在不修改 ShoppingCart 类的情况下,动态地添加输入验证、日志记录和性能监控功能。
  • 单一职责原则:每个装饰器只负责特定的功能,确保代码的清晰性和可维护性。
  • 可扩展性:可以轻松地添加新的装饰器来扩展功能,例如添加新的日志记录方式或其他验证逻辑,而不需要修改现有的代码结构。

4. 例子 2:复杂函数的装饰器传参

def process_order(user, product_name, quantity, price_per_item, discount=0, tax_rate=0.1):total_price = quantity * price_per_itemtotal_price -= total_price * (discount / 100)  # 应用折扣total_price += total_price * tax_rate  # 应用税费return f"{user}, the total price for {quantity} {product_name}(s) is: ${total_price:.2f}"def log_order(log_level="INFO"):def decorator(func):def wrapper(*args, **kwargs):user = args[0]  # 获取用户product_name = args[1]  # 获取产品名称quantity = args[2]  # 获取数量price_per_item = args[3]  # 获取单价discount = kwargs.get('discount', 0)  # 获取折扣tax_rate = kwargs.get('tax_rate', 0.1)  # 获取税率if log_level == "DEBUG":print(f"DEBUG: Processing order for {user}: {quantity} {product_name}(s) at ${price_per_item} each, "f"with a discount of {discount}% and a tax rate of {tax_rate * 100}%.")elif log_level == "INFO":print(f"INFO: Processing order for {user}.")result = func(*args, **kwargs)  # 调用原始函数return resultreturn wrapperreturn decorator@log_order(log_level="DEBUG")  # 指定日志级别为 DEBUG
def process_order(user, product_name, quantity, price_per_item, discount=0, tax_rate=0.1):total_price = quantity * price_per_itemtotal_price -= total_price * (discount / 100)  # 应用折扣total_price += total_price * tax_rate  # 应用税费return f"{user}, the total price for {quantity} {product_name}(s) is: ${total_price:.2f}"if __name__ == "__main__":user = "Alice"product_name = "Laptop"quantity = 2price_per_item = 1000discount = 10  # 10% 折扣tax_rate = 0.1  # 10% 税率# 调用处理订单的函数result = process_order(user, product_name, quantity, price_per_item, discount=discount, tax_rate=tax_rate)print(result)
DEBUG: Processing order for Alice: 2 Laptop(s) at $1000 each, with a discount of 10% and a tax rate of 10.0%.
Alice, the total price for 2 Laptop(s) is: $2180.00
  1. 复杂函数:我们定义了一个复杂的函数 process_order,它接受多个参数并计算总价。
  2. 带参数的装饰器:我们创建了一个装饰器 log_order,它接受一个参数 log_level,用于控制日志的详细程度。
  3. 参数传递:在装饰器中,我们使用 *args**kwargs 来确保能够接受任意数量的位置参数和关键字参数,并在调用原始函数时正确传递这些参数。
  • *args:用于接收可变数量的位置参数。它将所有额外的位置参数收集到一个元组中。
  • **kwargs:用于接收可变数量的关键字参数。它将所有额外的关键字参数收集到一个字典中。
def my_decorator(func):def wrapper(*args, **kwargs):# 在调用原始函数之前,可以处理参数print("Inside decorator:")print("Position arguments (args):", args)  # 打印所有位置参数print("Keyword arguments (kwargs):", kwargs)  # 打印所有关键字参数# 调用原始函数,并将参数传递给它result = func(*args, **kwargs)# 在调用原始函数之后,可以处理返回值return resultreturn wrapper@my_decorator
def greet(name, greeting="Hello"):return f"{greeting}, {name}!"# 调用被装饰的函数
result = greet("Alice", greeting="Hi")
print(result)
Inside decorator:
Position arguments (args): ('Alice',)
Keyword arguments (kwargs): {'greeting': 'Hi'}
Hi, Alice!
  • 位置参数

    • 当调用 greet("Alice", greeting="Hi") 时,"Alice" 被收集到 args 中,成为一个元组 ('Alice',)
    • args[0] 访问第一个位置参数,值为 'Alice'
  • 关键字参数

    • greeting="Hi" 被收集到 kwargs 中,成为一个字典 {'greeting': 'Hi'}
    • kwargs['greeting'] 访问关键字参数 greeting,值为 'Hi'
  • 调用原始函数

    • 在装饰器的 wrapper 函数中,使用 func(*args, **kwargs) 调用原始函数 greet,并将所有参数传递给它。

5. 例子 3:类函数装饰器传参

def log_method_call(log_level="INFO"):def decorator(func):def wrapper(self, *args, **kwargs):if log_level == "DEBUG":print(f"DEBUG: Calling method '{func.__name__}' with arguments: {args} and keyword arguments: {kwargs}")elif log_level == "INFO":print(f"INFO: Calling method '{func.__name__}'")result = func(self, *args, **kwargs)  # 调用原始方法return resultreturn wrapperreturn decoratorclass Calculator:@log_method_call(log_level="DEBUG")  # 使用装饰器并传递参数def add(self, a, b, *args, **kwargs):print("Additional positional arguments (args):", args)print("Additional keyword arguments (kwargs):", kwargs)return a + b@log_method_call(log_level="INFO")  # 使用装饰器并传递参数def subtract(self, a, b, *args, **kwargs):print("Additional positional arguments (args):", args)print("Additional keyword arguments (kwargs):", kwargs)return a - bif __name__ == "__main__":calc = Calculator()# 调用加法方法result_add = calc.add(5, 3, 10, 20, extra="value")print("Result of addition:", result_add)# 调用减法方法result_subtract = calc.subtract(10, 4, 5, 15, another="value")print("Result of subtraction:", result_subtract)
DEBUG: Calling method 'add' with arguments: (10, 20) and keyword arguments: {'extra': 'value'}
Additional positional arguments (args): (10, 20)
Additional keyword arguments (kwargs): {'extra': 'value'}
Result of addition: 8
INFO: Calling method 'subtract'
Additional positional arguments (args): (5, 15)
Additional keyword arguments (kwargs): {'another': 'value'}
Result of subtraction: 6
  • 装饰器的灵活性:通过使用 *args**kwargs,装饰器能够处理任意数量的位置参数和关键字参数。这使得装饰器在处理类方法时非常灵活,可以适应不同的调用场景。

  • 参数传递:在 Calculator 类的 addsubtract 方法中,*args 收集了额外的位置参数,而 **kwargs 收集了额外的关键字参数。这使得方法能够处理更多的输入,而不需要事先定义所有可能的参数。

  • 日志记录:装饰器根据 log_level 参数的不同,提供了不同级别的日志信息。在调试时,可以选择更详细的日志输出,而在生产环境中,可以选择更简洁的日志信息。

  • 代码复用:通过使用装饰器,我们可以将日志记录的逻辑与业务逻辑分离,使得代码更加清晰和可维护。装饰器可以轻松地应用于其他方法,而无需重复编写日志记录的代码。

相关文章:

Python 装饰模式

在软件开发中&#xff0c;随着系统的复杂性增加&#xff0c;需求的变化往往会导致代码的频繁修改。为了提高代码的灵活性和可维护性&#xff0c;设计模式应运而生。其中&#xff0c;装饰模式&#xff08;Decorator Pattern&#xff09;是一种非常实用的结构型设计模式&#xff…...

JVM 面经

1、什么是 JVM? JVM 就是 Java 虚拟机&#xff0c;它是 Java 实现跨平台的基石。程序运行之前&#xff0c;需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件&#xff1b;程序运行时&#xff0c;JVM 会对字节码文件进行逐行解释&#xff0c;翻译成机器码指令&#x…...

java对pdf文件分页拆分

文章目录 pdf文件拆分指定分页大小 pdf文件拆分 导入依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.32</version></dependency>2. 大文件拆分public static boolean …...

【PGCCC】PostgreSQL Certified Master 个人专访 | 第二期 何雄

由PGCCC发起的“PostgreSQL Certified Master个人专访”栏目&#xff0c;旨在挖掘PCM们对数据库行业的深度洞察&#xff0c;分享他们对行业发展的思考和个人感悟&#xff0c;对广大PGer们具有实际借鉴意义。 1.请简单介绍一下自己,您的爱好、您的事业。 大家好&#xff0c;我…...

什么是具身智能

具身智能&#xff08;Embodied Intelligence&#xff09;是人工智能与机器人学交叉的前沿领域&#xff0c;强调智能体通过身体与环境的动态交互实现自主学习和进化&#xff0c;其核心在于将感知、行动与认知深度融合‌。通俗地讲&#xff0c;就是机器人或者智能系统在物理环境中…...

Android开发EmojiCompat 初始化

Android开发EmojiCompat 初始化 报错信息&#xff1a; ensure spannable:java.lang.IllegalStateException: EmojiCompat is not initialized 在Application上写上下面代码即可&#xff1a; EmojiCompat.Config config new BundledEmojiCompatConfig(this);EmojiCompat.in…...

k近邻算法K-Nearest Neighbors(KNN)

算法核心 KNN算法的核心思想是“近朱者赤&#xff0c;近墨者黑”。对于一个待分类或预测的样本点&#xff0c;它会查找训练集中与其距离最近的K个样本点&#xff08;即“最近邻”&#xff09;。然后根据这K个最近邻的标签信息来对当前样本进行分类或回归。 在分类任务中&#…...

TextGrad:案例

原文&#xff1a;Yuksekgonul, M., Bianchi, F., Boen, J. et al. Optimizing generative AI by backpropagating language model feedback. Nature 639, 609–616 (2025). https://doi.org/10.1038/s41586-025-08661-4 目录 Solution optimizationPrompt optimization for rea…...

位运算算法:解锁高效编程的钥匙

常见位运算场景&#xff1a; 5.消失的两个数字 1.判定字符是否唯一 解法一&#xff1a;使用HashSet 借助 HashSet 存储字符。HashSet 不允许有重复元素&#xff0c;在遍历字符串时尝试添加字符&#xff0c;若添加失败就表明有重复字符&#xff0c;返回 false&#xff1b;若遍…...

Burp Suite抓包实战:SQL注入漏洞挖掘

本文系统解析如何利用Burp Suite专业版开展SQL注入漏洞的定向挖掘&#xff0c;涵盖手动探测、自动化利用、WAF绕过等进阶技巧。通过电商、金融等行业的真实渗透案例&#xff0c;详解从流量拦截到漏洞利用的全链路方法论&#xff0c;实现单日最高挖掘23个高危注入点的实战成果。…...

使用HTML5和CSS3实现3D旋转相册效果

使用HTML5和CSS3实现3D旋转相册效果 这里写目录标题 使用HTML5和CSS3实现3D旋转相册效果项目介绍技术栈核心功能实现思路1. HTML结构2. CSS样式解析2.1 基础样式设置2.2 3D效果核心样式2.3 卡片样式 3. JavaScript交互实现3.1 旋转控制3.2 自动播放功能 技术要点总结项目亮点总…...

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案

✅ MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案 前言一、问题现象二、原因分析1. 使用了 strictInsertFill/strictUpdateFill 导致更新失效2. 实体类注解配置错误3. MetaObjectHandler 未生效4. 使用自定义 SQL 导致自动填充失效5. 字段类型不匹配 三、…...

MySQL Binlog

MySQL Binlog MySQL Binlog 介绍查看 Binlog 位点开启和关闭 BinlogBinlog 的作用Binlog 记录的格式Binlog 的解析Binlog 加密Binlog 的清理根据Binlog文件名删除根据时间删除 Binlog 保留参数Binlog 的落盘Binlog 相关参数 MySQL主从复制&#xff1a;https://blog.csdn.net/a…...

SQL中累计求和与滑动求和函数sum() over()的用法

[TOC](SQL中累计求和与滑动求和函数sum() over()的用法) 一、窗口函数功能简介 sum(c) over(partition by a order by b) 按照一定规则汇总c的值&#xff0c;具体规则为以a分组&#xff0c;每组内按照b进行排序&#xff0c;汇总第一行至当前行的c的加和值。 sum()&#xff1a…...

第十四届MathorCup高校数学建模挑战赛-C题:基于 LSTM-ARIMA 和整数规划的货量预测与人员排班模型

目录 摘要 一、 问题重述 1.1 背景知识 1.2 问题描述 二、 问题分析 2.1 对问题一的分析 2.2 对问题二的分析 2.3 对问题三的分析 2.4 对问题四的分析 三、 模型假设 四、 符号说明 五、 问题一模型的建立与求解 5.1 数据预处理 5.2 基于 LSTM 的日货量预测模型 5.3 日货量预测…...

3d pose 指标和数据集

目录 3D姿态估计、3维重建指标: 数据集 EHF数据集 SMPL-X 3D姿态估计、3维重建指标: MVE、PMVE 和 p-MPJPE 都是用于评估3D姿态估计、三维重建等任务中预测结果与真实数据之间误差的指标。 MVE (Mean Vertex Error):是指模型重建过程中每个顶点的预测位置与真实位置之间…...

【MySQL】InnoDB中的MVCC

目录 1、背景2、设置事务的隔离级别3、MVCC【1】版本链【2】ReadView【3】ReadView的生成时机 4、总结 1、背景 MVCC叫做多版本并发控制&#xff0c;通过维护数据的多个历史版本实现读写分离&#xff1a;读操作访问快照版本&#xff0c;无需加锁&#xff0c;避免阻塞写操作&am…...

从DeepSeek到Qwen,AI大模型的移植与交互实战指南

在不久前发布的《技术实战 | OK3588-C开发板上部署DeepSeek-R1大模型的完整指南》一文中&#xff0c;小编为大家介绍了DeepSeek-R1在飞凌嵌入式OK3588-C开发板上的移植部署、效果展示以及性能评测&#xff0c;本篇文章不仅将继续为大家带来关于DeepSeek-R1的干货知识&#xff0…...

蓝桥杯Java组国赛G题(01背包问题的变形)

题目 解题思路 首先&#xff0c;解决此题的前置知识是需要掌握普通的 01 背包问题。当然&#xff0c;这题肯定不可能这么简单。题目相对于 01 背包来说&#xff0c;唯一的区别在于小蓝可以使用 1 次魔法。我们只需要多加一维状态记录是否使用了魔法即可。下面考虑动态规划&…...

QCW模式:准连续波驱动在VCSEL激光器中的技术解析与应用价值

点击下面图片&#xff0c;为您提供全新的嵌入式学习路线 文章目录 一、QCW模式的定义与工作原理二、QCW模式的技术优势三、典型应用场景分析四、PLD850-5mW-MV的QCW性能亮点五、总结 一、QCW模式的定义与工作原理 QCW&#xff08;Quasi-Continuous Wave&#xff09;&#xf…...

C++List模拟实现|细节|难点|易错点|全面解析|类型转换|

目录 1.模拟代码全部 2.四大块代码理解 1.最底层&#xff1a;ListNode部分 2.第二层&#xff1a;ListIterator部分 3.第三层&#xff1a;ReserveListIterator部分 4最终层&#xff1a;List 1.模拟代码全部 using namespace std; template<class T> struct ListNode …...

【安全】记录钓鱼邮件中木马病毒的分析溯源

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 1、收到一封邮件&#xff0c;与以往钓鱼网站形式不同&#xff0c;这次是给了一个exe可执行文件。毫无疑问&#xff0c;肯定是植入木马用的。 下载后&am…...

三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&…...

AI 与 IT 从业者:共舞还是取代?

在当今数字化浪潮的汹涌冲击下&#xff0c;AI 的出现犹如一颗划破夜空的璀璨星辰&#xff0c;照亮了科技发展的新方向&#xff0c;也引发了无数关于未来职业走向的讨论。尤其是对于 IT 从业者而言&#xff0c;仿佛站在了一个十字路口&#xff0c;前方是机遇与挑战交织的未知旅程…...

【计算机网络中的奈氏准则与香农定理】

文章目录 一、前言二、奈氏准则1. 概念2. 奈氏准则公式3. 奈氏准则的意义 三、香农定理1. 概念2. 香农定理公式3. 香农定理的意义 四、奈氏准则与香农定理的对比五、应用示例1. 奈氏准则示例2. 香农定理示例 六、总结 一、前言 在计算机网络中&#xff0c;数据的传输速率与信道…...

湖南(源点咨询)市场调研 商业综合体定位调研分享(上篇)

​ 该项目位于某新一线城市的城市副中心区域&#xff0c;系一个正在发展中的中央居住区&#xff0c;项目本身是一个涵盖社区综合服务中心、商业、文体活动中心、卫生服务、社区养老等多功能复合的公共配套项目&#xff0c;本次调研主要针对其商业&#xff08;及其他可商用的&a…...

鸿蒙ArkTs/c++/RepalcePioneer/base64.us之Base64编码解码的是非

狗血现象&#xff1a; 同一字符串原文使用 1、RepalcePioneer&#xff08;一款Windows平台的字符串工具&#xff09; 2、鸿蒙ArkTs自带base64编码方法 3、https://base64.us&#xff08;一款在线base64工具&#xff09; 来编码&#xff0c;得到编码串不一样&#xff0c;后…...

《Linux运维实战:Ubuntu 22.04使用pam_faillock实现登录失败处理策略》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;Linux运维实战总结 一、背景信息 在ubuntu 22.04中&#xff0c;pam_tally2模块已被弃用&#xff0c;取而代之的是pam_faillock模块。因此&#xf…...

如何让DeepSeek-R1在内网稳定运行并实现随时随地远程在线调用

前言&#xff1a;最近&#xff0c;国产AI圈里的新星——Deepseek&#xff0c;简直是火到不行。但是&#xff0c;你是不是已经对那些千篇一律的手机APP和网页版体验感到腻味了&#xff1f;别急&#xff0c;今天就带你解锁一个超炫的操作&#xff1a;在你的Windows电脑上本地部署…...

2.1-WAF\CDN\OSS\反向代理\负载均衡

WAF&#xff1a;就是网站应用防火墙&#xff0c;有硬件类、软件类、云WAF&#xff1b; 还有网站内置的WAF&#xff0c;内置的WAF就是直接嵌在代码中的安全防护代码 硬件类&#xff1a;Imperva、天清WAG 软件&#xff1a;安全狗、D盾、云锁 云&#xff1a;阿里云盾、腾讯云WA…...

matplotlib学习

开始学习Python数据可视化 一.基础绘图函数 1.创建画布与坐标轴 import matplotlib.pyplot as plt# 创建画布和坐标轴 fig, ax plt.subplots() # 默认1行1列&#xff0c;返回Figure对象和Axes对象 2.绘制线图 x [1, 2, 3, 4] y [10, 20, 15, 25]# 绘制线图 ax.plot(x,…...

Go 语言标准库中math模块详细功能介绍与示例

Go语言的 math 模块提供了丰富的数学函数和常量&#xff0c;涵盖基本运算、三角函数、指数、对数、取整、特殊值等。以下是核心方法及示例说明&#xff1a; 1. 基本数学运算 math.Abs 取绝对值&#xff08;仅 float64&#xff09;。 fmt.Println(math.Abs(-3.5)) // 输出:…...

RabbitMQ三种队列深度解析:区别、场景与未来趋势

嗯&#xff0c;用户让我分析RabbitMQ三种队列的区别、应用场景、技术原理和未来趋势&#xff0c;还要写一篇三千字的文章。首先&#xff0c;我需要回顾一下搜索结果&#xff0c;看看有哪些资料可用。 根据搜索结果&#xff0c;RabbitMQ的三种队列是经典队列&#xff08;Classi…...

15. 三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&…...

0328-内存图2

是否正确待定&#xff1a; Perso类 package com.qc.内存图2;public class Perso {public int age;public String name;public static int flag;public void m1() {}public static void m2() {}Overridepublic String toString() {return "Perso [age" age "…...

最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1&#xff1a; 输入&#xff1a;nums [-1,2,1,-4], target 1 输出&#xff1a;…...

d2025328

一、sql-判断三角形 610. 判断三角形 - 力扣&#xff08;LeetCode&#xff09; 用一下if加上判断条件 select x,y,z,if(xy > z and xz > y and yz > x and x-y < z and x-z < y and y-z < x,Yes,No) as triangle from Triangle 二、按照分类统计薪水 190…...

初识MySQl · 内置函数

目录 前言&#xff1a; 日期类函数 字符串函数 数学类函数 其他函数 前言&#xff1a; 在前文的学习我们已经简单了解了部分函数&#xff0c;比如count()函数什么的&#xff0c;今天我们主要是笼统的学习一下MySQL中的函数&#xff0c;仅仅从使用的角度来学习&#xff0c…...

(C语言)指针运算 习题练习1.2(压轴难题)

在上一张已经练习了三道习题&#xff0c;小试牛刀了&#xff0c;那么在本章在来几题&#xff0c;练练手。&#xff08;习题三是压轴难题&#xff09; 习题一 int main() {int aa[2][5] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 (int*)(&aa 1);int* ptr2 (int*)…...

视频AI赋能水利行业生态治理,水电站大坝漂浮物实时监测与智能预警方案

水电站大坝周边水域垃圾漂浮物不仅影响水质&#xff0c;还可能对大坝设施运行、水生态环境造成威胁。传统依靠人工巡检的方式效率低、存在监测盲区&#xff0c;难以实时全面地掌握漂浮物情况。借助EasyCVR视频汇聚平台与TSINGSEE青犀AI算法中台构建智能化监测方案&#xff0c;能…...

方阵幂次(矩阵快速幂)

#include <bits/stdc.h> using namespace std;int n; vector<vector<int>> fuc(vector<vector<int>> a,vector<vector<int>> b){ // 矩阵乘法函数vector<vector<int>> f(n,vector<int>(n));for(int i0;i<n;i){…...

【Uni-App】嵌入悬浮球全局组件的详细教程和防踩坑点

一、前言 近期接到一个业务需求是为为h5页面嵌入悬浮球&#xff0c;而且还得是全局化&#xff08;这样所有页面就可以看见了&#xff09;&#xff0c;在开发的过程中也遇到一些坑&#xff0c;在此和大家一起学习、讨论。 二、准备工作 下载悬浮球组件代码 悬浮球 - DCloud …...

第十六章 图

1.为什么要有图 前面学了线性表和树 线性表局限于一个直接前驱和一个直接后继的关系 树也只能有一个直接前驱也就是父节点 当我们需要表示多对多的关系时,这里我们就用到了图 import java.util.ArrayList; import java.util.Arrays;public class Graph {private int[][]edg…...

Ubuntu 系统无法远程连接?完整排查指南与解决方案

远程连接 Ubuntu 系统是服务器管理和开发中的常见需求,但有时会遇到无法连接的问题。本文整理常见原因及解决方法,涵盖 SSH 服务配置、防火墙规则、网络设置等关键环节,助您快速定位问题。 检查 SSH 服务状态 SSH(Secure Shell) 是远程连接的核心服务。若未安装或未运行,…...

将网络安全和第三方风险管理与业务目标相结合

在网络安全风险领域&#xff0c;我们经常遇到与企业语言不通的问题。这可能导致网络安全风险管理计划得不到支持。当发现网络安全风险时&#xff0c;困难在于以符合组织语言和目标的方式来表达它。 第三方风险属于另一个灰色地带。在组织内部&#xff0c;许多利益相关者&#…...

加油站小程序实战教程02宫格导航

目录 引言1 应用创建2 搭建页面布局3 大模型生成图标最终效果 引言 在《加油站小程序实战教程01》中我们详细介绍了站点基本信息数据维护功能的搭建。有了数据之后就需要考虑小程序展示部分该如何搭建&#xff0c;本篇我们介绍一下应用的创建、页面布局以及数据绑定的过程。 …...

es6的箭头函数与普通函数的区别,箭头函数的this通常指向哪里,箭头函数可以用作构造函数吗?

ES6 的箭头函数与普通函数的区别 箭头函数&#xff08;Arrow Function&#xff09;和普通函数有一些重要的区别&#xff0c;主要体现在以下几个方面&#xff1a; 1. 语法简洁性 - 箭头函数的语法更简洁&#xff0c;不需要使用 function 关键字。 - 普通函数需要使用 functi…...

工作记录 2017-03-10

工作记录 2017-03-10 序号 工作 相关人员 1 修改邮件上的问题。 更新RD服务器。 郝 更新的问题 1、修改了payment detail和patient insurance的health plan的输入方式。 2、new payment detail时&#xff0c;增加了allowable的处理。 3、选择payer的窗体&#xff0c;增…...

如何一键安装所有Python项目的依赖!

在开发项目时&#xff0c;常常需要在多个环境中安装各种依赖。对开发者来说&#xff0c;每次手动一个个安装这些依赖是不是很麻烦&#xff1f;&#x1f605; 其实有个超简单的办法&#xff01;只需要一个脚本&#xff0c;就能快速解决问题&#xff01;&#x1f4a1; 这就是我们…...

linux的基础命令

目录 1. 文件和目录操作 ls ls -l ls -a pwd touch haha.txt mkdir 113 cd . 和 cd .. cd ~ echo "hello world" >> test.c cat test.txt mv rm 2. 压缩与解压 zip test.zip test.c unzip test.zip -d /root/113 tar czf lesson4.tgz less…...