python编程-装饰器

目录

一、装饰器的概念

装饰器与设计模式的关联

二、装饰器的基本结构和语法

1. 函数装饰器

定义装饰器函数:

应用装饰器到函数:

方式一:使用@符号(语法糖)

方式二:手动调用装饰器函数

函数装饰器的更多细节

包装函数的参数传递灵活性

包装函数的返回值处理

2. 类装饰器

定义类装饰器类:

应用类装饰器到函数:

方式一:使用@符号(语法糖)

方式二:手动调用类装饰器类

类装饰器的更多细节

类装饰器与类的继承关系

三、装饰器的参数传递

1. 函数装饰器带参数

2. 类装饰器带参数

3.多层嵌套装饰器带参数

四、装饰器的应用场景

1. 日志记录

2. 权限验证

3. 性能计时

4.缓存功能

5.输入验证

五、装饰器的执行顺序

装饰器执行顺序与函数调用顺序的关系

六、装饰器的注意事项

1. 保留原函数的元信息

2.保留原函数元信息的重要性及影响

3. 闭包和变量作用域

4.闭包和变量作用域的更多示例


一、装饰器的概念

装饰器是一种在 Python 中用于修改其他函数或类的行为的高级语法结构,本质上它是一个函数(也可以是一个类,但相对较少见),这个函数接受一个函数或类作为输入,并返回一个经过修改后的函数或类。其主要目的是在不修改原函数或类的代码本身的基础上,为它们添加额外的功能,比如日志记录、权限验证、性能计时等。

 

装饰器与设计模式的关联

装饰器在某种程度上可以看作是 Python 语言对装饰器设计模式的一种实现。装饰器设计模式的核心思想是在不改变被装饰对象(函数或类)原有结构和功能的基础上,动态地为其添加额外的功能。这种模式在很多编程语言中都有类似的实现方式,而 Python 通过其简洁的语法(如函数和类作为装饰器以及 @ 语法糖)使得装饰器的使用更加方便和直观。

例如,在一个大型的软件项目中,可能有多个不同功能的模块,每个模块都包含许多函数。如果要为这些函数统一添加日志记录功能,使用装饰器就可以遵循装饰器设计模式的思路,在不逐个修改函数内部代码的情况下,轻松实现日志记录功能的添加,提高了代码的可维护性和扩展性,符合软件设计中开闭原则(对扩展开放,对修改关闭)的要求。

二、装饰器的基本结构和语法

1. 函数装饰器

  • 定义装饰器函数

 装饰器函数通常接受一个函数作为参数,并在其内部定义一个新的函数(称为包装函数或闭包函数)来对传入的函数进行包装和修改。例如:

def my_decorator(func):def wrapper(*args, **kwargs):# 在调用原函数之前可以添加一些操作print("在调用函数之前执行一些操作")result = func(*args, **kwargs)# 在调用原函数之后可以添加一些操作print("在调用函数之后执行一些操作")return resultreturn wrapper

在上述例子中,my_decorator就是一个装饰器函数,它接受一个函数func作为参数,并返回一个包装函数wrapper

  • 应用装饰器到函数

要将装饰器应用到一个函数上,可以使用两种常见的语法方式。

 

方式一:使用@符号(语法糖)
@my_decorator
def add_numbers(a, b):return a + b

这种方式是在定义要被装饰的函数时,在函数定义的上一行加上@装饰器函数名,就相当于执行了add_numbers = my_decorator(add_numbers),即将add_numbers函数传递给my_decorator进行装饰,并将返回的包装后的函数重新赋值给add_numbers变量,这样当调用add_numbers函数时,实际上执行的是经过装饰后的函数。

方式二:手动调用装饰器函数
def add_numbers(a, b):return a + bdecorated_add_numbers = my_decorator(add_numbers)

这里先定义了add_numbers函数,然后通过手动调用my_decorator并传入add_numbers函数,将返回的包装后的函数赋值给decorated_add_numbers变量,之后调用decorated_add_numbers就相当于调用经过装饰后的函数。

函数装饰器的更多细节

包装函数的参数传递灵活性

在函数装饰器中,包装函数(wrapper的参数传递方式非常灵活。除了常见的接受位置参数(*args)和关键字参数(**kwargs来匹配被装饰函数可能的各种参数形式外,还可以根据具体需求对参数进行进一步的处理。

例如,假设被装饰函数可能接受一个特定类型的参数,如一个字典,并且在装饰器中需要对这个字典参数进行一些预处理。可以在包装函数中对传入的参数进行判断和处理,如下所示:

def my_decorator(func):def wrapper(*args, **kwargs):if 'data_dict' in kwargs:kwargs['data_dict'] = preprocess_dict(kwargs['data_dict'])result = func(*args, **kwargs)return resultreturn wrapperdef preprocess_dict(data_dict):# 这里进行对字典的预处理操作,比如添加一些默认键值对data_dict.setdefault('default_key', 'default_value')return data_dict@my_decorator
def my_function(data_dict):print(data_dict)my_function({'key': 'value'})

在上述示例中,装饰器的包装函数 wrapper 在调用被装饰函数 my_function 之前,先检查是否有名为 data_dict 的关键字参数,如果有则对其进行预处理操作,然后再将处理后的参数传递给 my_function

包装函数的返回值处理

包装函数对于被装饰函数的返回值也可以进行灵活的处理。除了简单地返回被装饰函数的执行结果外,还可以根据需要对返回值进行进一步的转换、验证等操作。

例如,假设被装饰函数返回一个数值,而在装饰器中希望对这个返回值进行范围验证,如果不在指定范围内则返回一个默认值。可以这样实现:

def my_decorator(func):def wrapper(*args, **kwargs):result = func(*args, **kwargs)if not (0 <= result <= 100):result = 0return resultreturn wrapper@my_decorator
def my_function():return 150print(my_function())

在这个示例中,包装函数 wrapper 在获取被装饰函数 my_function 的返回值后,对其进行了范围验证,如果返回值不在 0 到 100 的范围内,则将返回值设置为 0,然后再返回处理后的结果。

 

2. 类装饰器

  • 定义类装饰器类:

类装饰器是通过定义一个类,在类的构造函数中接收要被装饰的函数或类,并在类中实现__call__方法来实现对传入对象的装饰。例如:

class MyClassDecorator:def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):# 在调用原函数之前可以添加一些操作print("在调用函数之前执行一些操作")result = self.func(*args, **kwargs)# 在调用原函数之后可以添加一些操作print("在调用函数之后执行一些操作")return result

在这个例子中,MyClassDecorator类就是一个类装饰器,它在构造函数中接收要被装饰的函数func,并在__call__方法中对该函数进行包装和修改。

  • 应用类装饰器到函数

应用类装饰器到函数的方式与应用函数装饰器类似,也可以使用@符号(语法糖)或手动调用类装饰器类。

方式一:使用@符号(语法糖)
@MyClassDecorator
def add_numbers(a, b):return a + b

这相当于执行了add_numbers = MyClassDecorator(add_numbers),即将add_numbers函数传递给MyClassDecorator进行装饰,并将返回的包装后的函数重新赋值给add_numbers变量,这样当调用add_numbers函数时,实际上执行的是经过装饰后的函数。

方式二:手动调用类装饰器类
def add_numbers(a, b):return a + bdecorated_add_numbers = MyClassDecorator(add_numbers)

先定义add_numbers函数,然后手动调用MyClassDecorator类并传入add_numbers函数,将返回的包装后的函数赋值给decorated_add_numbers变量,之后调用decorated_add_numbers就相当于调用经过装饰后的函数。

 

 

类装饰器的更多细节

类装饰器与类的继承关系

当使用类装饰器对一个类进行装饰时,除了可以在 __call__ 方法中对类的实例方法进行包装和修改外,还可以利用类的继承关系来实现更复杂的装饰功能。

例如,假设我们有一个基类 BaseClass,想要通过类装饰器为从这个基类派生的类添加一些通用的属性和方法。可以定义一个类装饰器如下:

class ClassDecoratorWithInheritance:def __init__(self, cls):self.cls = clsdef __call__(self, *args, **kwargs):class DecoratedClass(self.cls):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.new_attribute = "这是新增的属性"def new_method(self):print("这是新增的方法")return DecoratedClass(*args, **kwargs)class BaseClass:def base_method(self):print("这是基类的方法")@ClassDecoratorWithInheritance
class DerivedClass(BaseClass):passobj = DerivedClass()
obj.base_method()
obj.new_method()
print(obj.new_attribute)

在上述示例中,类装饰器 ClassDecoratorWithInarchy 在其 __call__ 方法中定义了一个新的类 DecoratedClass,这个新类继承自被装饰的类 self.cls(即 DerivedClass 的基类 BaseClass)。在新类中,添加了新的属性 new_attribute 和新的方法 new_method。当创建 DerivedClass 的实例时,实际上得到的是经过装饰后的 DecoratedClass 的实例,从而实现了为派生类添加通用属性和方法的功能。

三、装饰器的参数传递

有时候我们希望装饰器本身也能接受一些参数,以便根据不同的参数值来对被装饰的函数或类进行不同方式的修饰。这可以通过在装饰器函数(或类)的外层再嵌套一层函数(或类)来实现。

1. 函数装饰器带参数

例如,我们想创建一个可以根据指定的日志级别来记录函数调用信息的装饰器:

def log_decorator(log_level):def decorator(func):def wrapper(*args, **kwargs):if log_level == "DEBUG":print(f"[DEBUG] 正在调用函数 {func.__name__}")elif log_level == "INFO":print(f"[INFO] 正在调用函数 {func.__name__}")result = func(*args, **kwargs)return resultreturn wrapperreturn decorator

在上述例子中,log_decorator函数接受一个log_level参数,它返回一个真正的装饰器函数decorator,这个decorator函数再接受要被装饰的函数func作为参数,并返回包装函数wrapper

应用这个带参数的装饰器可以这样做:

@log_decorator("DEBUG")
def add_numbers(a, b):return a + b

这里通过@log_decorator("DEBUG")add_numbers函数进行装饰,根据指定的DEBUG日志级别来记录函数调用信息。

2. 类装饰器带参数

同样,对于类装饰器也可以实现带参数的功能。例如:

class LogClassDecorator:def __init__(self, log_level):self.log_level = log_leveldef __call__(self, func):def wrapper(*args, **kwargs):if self.log_level == "DEBUG":print(f"[DEBUG] 正在调用函数 {func.__name__}")elif self.log_level == "INFO":print(f"[INFO] 正在调用函数 {func.__name__}")result = func(*args, **kwargs)return resultreturn wrapper

应用这个带参数的类装饰器可以这样做:

@LogClassDecorator("DEBUG")
def add_numbers(a, b):return a + b

3.多层嵌套装饰器带参数

除了常见的一层嵌套实现装饰器带参数的情况,还可以有多层嵌套的装饰器带参数的情况。

例如,假设我们想创建一个装饰器,它不仅可以根据指定的日志级别记录函数调用信息,还可以根据指定的模块名称来进一步细分日志记录。可以这样实现:

def log_decorator(module_name):def inner_log_decorator(log_level):def decorator(func):def wrapper(*args, **kwargs):if log_level == "DEBUG":print(f"[{module_name}][DEBUG] 正在调用函数 {func.__name__}")elif log_level == "INFO":print(f"[{module_name}][INFO] 正在调用函数 {func.__name__}")result = func(*args, **kwargs)return resultreturn wrapperreturn decoratorreturn inner_log_decorator@log_decorator('add_number')(log_level="DEBUG")
def add_numbers(a, b):return a + badd_numbers(1, 2)

在上述示例中,log_decorator 函数先接受一个 module_name 参数,然后返回一个 inner_log_decorator 函数,这个函数又接受一个 log_level 参数,最后返回真正的装饰器函数 decorator。通过这样的多层嵌套,实现了根据指定的模块名称和日志级别来记录函数调用信息的功能。

四、装饰器的应用场景

装饰器在 Python 编程中有广泛的应用场景,以下是一些常见的例子:

1. 日志记录

如前面提到的根据不同日志级别记录函数调用信息,通过装饰器可以很方便地在不修改函数本身代码的情况下添加日志功能。例如:

def log_decorator(log_level):def decorator(func):def wrapper(*args, **kwargs):if log_level == "DEBUG":print(f"[DEBUG] 正在调用函数 {func.__name__}")elif log_level == "INFO":print(f"[INFO] 正在调用函数 {func.__name__}")result = func(*args, **kwargs)return resultreturn wrapperreturn decorator@log_decorator("DEBUG")
def my_function():print("执行我的函数")my_function()

2. 权限验证

可以通过装饰器来验证用户是否具有执行某个函数的权限。例如:

def permission_decorator(required_permission):def decorator(func):def wrapper(*args, **kwargs):user_permission = get_user_permission()  # 假设这是一个获取用户权限的函数if user_permission == required_permission:result = func(*args, **kwargs)return resultelse:print("你没有执行此函数的权限")return wrapperreturn decorator@permission_decorator("admin")
def admin_function():print("执行管理员函数")admin_function()

在这个例子中,通过permission_decorator装饰器来验证用户是否具有admin权限,如果有则执行admin_function,否则提示没有权限。

3. 性能计时

可以使用装饰器来测量函数的执行时间,以便分析函数的性能。例如:

import timedef time_decorator(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"函数 {func.__name__} 的执行时间为: {end_time - start_time}秒")return resultreturn wrapper@time_decorator
def slow_function():time.sleep(2)print("执行慢函数")slow_function()

在这个例子中,time_decorator装饰器在函数调用前后分别记录时间,然后计算并输出函数的执行时间。

4.缓存功能

装饰器可以用于实现函数的缓存功能,即对于一些计算成本较高的函数,当再次调用时,如果输入参数相同,则直接返回上次计算的结果,而不需要重新计算。

例如:

import functoolsdef cache_decorator(func):cache = {}@functools.wraps(func)def wrapper(*args, **kwargs):# 将位置参数和关键字参数转换为可哈希的形式作为键key = (args, tuple(sorted(kwargs.items())))if key in cache:return cache[key]result = func(*args, **kwargs)cache[key] = resultreturn resultreturn wrapper@cache_decorator
def expensive_function(x):print("正在计算昂贵函数...")return x * xprint(expensive_function(3))
print(expensive_function(3))

在上述示例中,cache_decorator 装饰器通过一个字典 cache 来存储已经计算过的函数结果。当再次调用被装饰函数 expensive_function 时,如果输入参数相同(通过将参数组合成一个元组作为键来判断),则直接从缓存中取出上次计算的结果返回,从而节省了计算资源。

5.输入验证

装饰器可以用于对函数的输入进行验证,确保输入符合一定的条件,否则提示错误信息

例如:

def input_validation_decorator(func):def wrapper(*args, **kwargs):if not all(isinstance(arg, int) for arg in args):print("输入必须为整数")returnresult = func(*args, **kwargs)return resultreturn wrapper@input_validation_decorator
def add_numbers(a, b):return a + badd_numbers(1, 2)
add_numbers('a', 'b')

在上述示例中,input_validation_decorator 装饰器在调用被装饰函数 add_numbers 之前,先检查输入参数是否都是整数,如果不是则提示错误信息并返回,否则继续执行被装饰函数并返回结果。

五、装饰器的执行顺序

当一个函数或类被多个装饰器修饰时,装饰器的执行顺序是按照从下往上(离函数或类定义最近的装饰器先执行)的顺序进行的。例如:

def decorator1(func):def wrapper(*args, **kwargs):print("装饰器1 - 在调用函数之前执行一些操作")result = func(*args, **kwargs)print("装饰器1 - 在调用函数之后执行一些操作")return resultreturn wrapperdef decorator2(func):def wrapper(*args, **kwargs):print("装饰器2 - 在调用函数之前执行一些操作")result = func(*args, **kwargs)print("装饰器2 - 在调用函数之后执行一些操作")return resultreturn wrapper@decorator1
@decorator2
def my_function():print("执行我的函数")my_function()

在这个例子中,首先执行decorator2my_function进行装饰,然后再执行decorator1对已经被decorator2装饰过的函数进行装饰。所以在调用my_function时,输出的顺序是:

装饰器2 - 在调用函数之前执行一些操作
装饰器1 - 在调用函数之前执行一些操作
执行我的函数
装饰器1 - 在调用函数之后执行一些操作
装饰器2 - 在调用函数之后执行一些操作

装饰器执行顺序与函数调用顺序的关系

装饰器的执行顺序是按照从下往上(离函数或类定义最近的装饰器先执行)的顺序进行的,这与函数调用顺序是相反的。当一个函数被多个装饰器修饰时,在调用该函数时,首先会执行最内层(离函数定义最近)的装饰器,然后依次往外执行其他装饰器。

例如,假设有三个装饰器 decorator1decorator2decorator3 修饰一个函数 my_function,按照如下顺序:

@decorator1
@decorator2
@decorator3
def my_function():print("执行我的函数")my_function()

在调用 my_function 时,首先执行 decorator3,对 my_function 进行第一次装饰,得到一个经过装饰后的函数 func1;然后执行 decorator2,对 func1 进行第二次装饰,得到 func2;最后执行 decorator1,对 func2 进行第三次装饰,得到最终的装饰后函数。在执行最终的装饰后函数时,按照相反的顺序,即先执行 decorator1 的包装函数中的操作,然后执行 decorator2 的包装函数中的操作,最后执行 decorator3 的包装函数中的操作。

六、装饰器的注意事项

1. 保留原函数的元信息

在使用装饰器对函数进行装饰后,原函数的一些元信息(如函数名、文档字符串、参数列表等)可能会丢失,这可能会影响到一些基于函数元信息的工具或库的使用。为了保留原函数的元信息,可以使用functools.wraps装饰器来装饰包装函数。例如:

from functools import wrapsdef my_decorator(func):@wraps(func)def wrapper(*args, **kwargs):print("在调用函数之前执行一些操作")result = func(*args, **kwargs)print("在调用函数之后执行一些操作")return resultreturn wrapper

通过使用functools.wraps装饰器装饰wrapper函数,可以确保原函数的元信息得以保留。

 

2.保留原函数元信息的重要性及影响

保留原函数的元信息不仅仅是为了满足一些基于函数元信息的工具或库的使用需求,它对于代码的可读性和可维护性也非常重要。

例如,在使用自动生成文档的工具(如 Sphinx)时,如果原函数的元信息丢失,那么生成的文档可能会缺少关于函数名称、参数列表、文档字符串等重要信息,导致文档的完整性和准确性受到影响。同样,在进行代码调试时,一些调试工具可能会依赖函数的元信息来准确显示函数的调用情况等,如果元信息丢失,调试过程也会受到影响。

 

3. 闭包和变量作用域

装饰器内部通常会形成闭包,在处理闭包和变量作用域时要特别注意。例如,如果装饰器函数中的包装函数需要修改外部函数(即装饰器函数)中的变量,可能需要使用nonlocal关键字来声明,以明确告知 Python 要修改的是外部函数中的那个变量。否则,可能会导致变量作用域混乱或无法正确修改变量的情况。

4.闭包和变量作用域的更多示例

除了前面提到的使用 nonlocal 关键字来声明要修改的外部函数中的非全局变量外,还有一些关于闭包和变量作用域的情况需要注意。

例如,假设装饰器函数中的包装函数需要引用外部函数(即装饰器函数)中的一个列表变量,并且在包装函数中需要对这个列表变量进行添加元素的操作。如果不注意变量作用域,可能会出现意外的结果。

def my_decorator(func):my_list = []def wrapper(*args, **kwargs):my_list.append(1)result = func(*args, **kwargs)return resultreturn wrapper@my_decorator
def my_function():print("执行我的函数")my_function()
my_function()

在上述示例中,每次调用 my_function 时,包装函数 wrapper 都会向 my_list 中添加一个元素。由于 my_list 是在装饰器函数 my_dectorator 中定义的,所以它的作用域涵盖了所有调用 my_function 的情况。这可能会导致一些意外的情况,比如如果后续需要根据 my_list 的状态来做一些判断或操作,就需要清楚地知道它在每次调用 my_function 时的变化情况

总之,装饰器是 Python 中一个非常强大的语法结构,通过合理运用它,可以在不修改原函数或类代码的基础上,为它们添加各种有用的功能,提高代码的可维护性和扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/58216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3+ts实时播放视频,视频分屏

使用vue3以及播放视频组件Jessibuca Jessibuca地址 使用循环个数来实现分屏 效果图&#xff0c;四屏 九屏 dom代码 <div class"icon"><div class"icon-box"><span class"text">分屏&#xff1a;</span><el-icon …

银行信贷风控专题:Python、R 语言机器学习数据挖掘应用实例合集:xgboost、决策树、随机森林、贝叶斯等

全文链接&#xff1a;https://tecdat.cn/?p38026 原文出处&#xff1a;拓端数据部落公众号 分析师&#xff1a;Fanghui Shao 在当今金融领域&#xff0c;风险管控至关重要。无论是汽车贷款违约预测、银行挖掘潜在贷款客户&#xff0c;还是信贷风控模型的构建&#xff0c;以及…

NF和C-BRUNO的区别

C-BRUNO与标准化流&#xff08;Normalizing Flow&#xff09;模型有一定的相似性&#xff0c;但它们在目标、应用和实现细节上存在明显的区别。以下是两者之间的主要区别&#xff1a; 1. 目标和应用领域 标准化流模型&#xff1a;标准化流的目标是通过一系列可逆变换将复杂的…

解决ElasticSearch启动成功却无法在浏览器访问问题

目录 前言&#xff1a; 问题复现 &#xff1a; 解决问题&#xff1a; 1、修改sysctl.conf文件 2、在sysctl.conf文件增加这段东西 3、 然后保存退出&#xff0c;输入以下命令使其生效 结语&#xff1a; 前言&#xff1a; 这篇文章是小白我今天突然启动es&#xff0c;发现e…

【华为HCIP实战课程二十五】中间到中间系统协议IS-IS配置实战续系统ID区域ID,网络工程师

上章简单讲解了ISIS基本配置,本章继续详细讲解ISIS配置及实施 IS-IS配置拓扑 1、R1进行配置IS-IS [R1]display current-configuration configuration isis isis 1 network-entity 49.0124.1111.1111.1111.00 //配置NET地址,由三部分组成,区域ID、系统ID和固定的SEL 00 i…

微服务之网关、网关路由、网关登录校验

简介&#xff1a;来源&#xff1a;SpringCloud微服务开发与实战&#xff0c;java黑马商城项目微服务实战开发&#xff08;涵盖MybatisPlus、Docker、MQ、ES、Redis高级等&#xff09; 认识网关 前端请求不能直接访问微服务&#xff0c;而是要请求网关&#xff1a; 网关可以做…

pytest执行用例时从conftest.py抛出ModuleNotFoundError:No module named ‘XXX‘异常的解决办法

问题描述 本地运行正常&#xff0c;集成到Jenkins后使用执行 Windows 批处理命令运行测试用例时报错&#xff1a; D:\PycharmProject\ZeppAndroid>pytest -vs testcase\test_login.py --alluredirreport/allure_json --clean-alluredir ImportError while loading conft…

手机收银云进销存管理软件,商品档案Excel格式批量导入导出,一键导入Excel的商品档案

如果您有Excel的商品档案&#xff0c;那么就可以批量导入到我们的手机云进销存软件系统里&#xff0c;就不需要人工手工一个个商品的新建商品档案&#xff0c;大大提高工作效率。如果您看下面的步骤不会操作&#xff0c;可以联系我们技术支持&#xff0c;来帮您把商品档案导入。…

DDRPHY数字IC后端设计实现系列专题

在对 LPDDR3 物理层接口模块进行后端设计之前&#xff0c;需要对该模块的功能结 构以及后端物理设计流程的相关理论进行深入的分析和研究。本章第一节详细分 析了本次 LPDDR3 物理层接口模块的结构&#xff0c;为该模块的布图布局的合理规划奠 定了理论基础&#xff0c;并且分析…

python机器人编程——一种3D骨架动画逆解算法的启示(上)

目录 一、前言二、fabrik 算法三、python实现结论PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源ps3.移动小车相关文章资源ps3.wifi小车控制相关文章资源 一、前言 我们用blender等3D动画软件时&#xff0c;会用到骨骼的动画&#xff0c;通过逆向IK动力学…

大数据之VIP(Virtual IP,虚拟IP)负载均衡

VIP&#xff08;Virtual IP&#xff0c;虚拟IP&#xff09;负载均衡是一种在计算机网络中常用的技术&#xff0c;用于将网络请求流量均匀地分散到多个服务器上&#xff0c;以提高系统的可扩展性、可靠性和性能。以下是对VIP负载均衡的详细解释&#xff1a; 一、VIP负载均衡的基…

想要音频里的人声,怎么把音频里的人声和音乐分开?

在音频处理领域&#xff0c;将音频中的人声和音乐分开是一个常见需求&#xff0c;尤其对于音乐制作、影视后期以及个人娱乐应用来说&#xff0c;这种分离技术显得尤为重要。随着科技的发展&#xff0c;现在已经有多种方法可以实现这一目的。 一、使用专业音频处理软件 市面上有…

快速学会C 语言基本概念和语法结构

&#x1f600;前言 本篇博文是关于C 语言的基本概念和语法结构&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力&a…

动态规划 —— 路径问题-不同路径 ||

1. 不同路径 || 题目链接&#xff1a; 63. 不同路径 II - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/unique-paths-ii/description/ 2. 算法原理 状态表示&#xff1a;以莫一个位置位置为结尾 dp[i]表示&#xff1a;以[i&#xff0c;j]位置为结尾时…

C++学习,冒泡排序

冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的&#xff0c;直到没有再需要交换的元素为止&#xff0c;这意…

Telephony IMS

1、IMS结构 IMS的启动过程,IMS业务依附于phone进程启动,当phone进程启动时拉起对应的框架代码。 当phone进程启动时,会启动ImsReslover类,该类用于寻找对应的IMS apk实现,并进行绑定。 当绑定成功后,ImsServiceController会保存IMS APK中的如下对象IImsRegistration IIms…

Consul微服务配置中心部署(在线安装)

博主介绍&#xff1a; 计算机科班人&#xff0c;全栈工程师&#xff0c;掌握C、C#、Java、Python、Android等主流编程语言&#xff0c;同时也熟练掌握mysql、oracle、sqlserver等主流数据库&#xff0c;具有丰富的项目经验和开发技能。提供相关的学习资料、程序开发、技术解答、…

Spring Task—定时任务

Spring Task 是 Spring 提供的一种轻量级定时任务调度功能&#xff0c;内置在 Spring 框架中。与 Quartz 等重量级调度框架相比&#xff0c;Spring Task 使用简便&#xff0c;无需额外依赖&#xff0c;适合在简单的调度任务场景中使用。通过注解配置方式&#xff0c;开发者可以…

DDR内存和Flash内存

DDR内存 DDRDouble Data Rate双倍速率同步动态随机存储器。严格的说DDR应该叫DDR SDRAM&#xff0c;人们习惯称为DDR&#xff0c;其中&#xff0c;SDRAM 是Synchronous Dynamic Random Access Memory的缩写&#xff0c;即同步动态随机存取存储器。而DDR SDRAM是Double Data Ra…

分布式数据库技术金融应用规范技术架构

目录 引 言 概述 技术框架 技术框架概述 物理资源层 计算模块 功能特性 功能架构概述 基本功能 部署灵活性 并发处理能力 扩缩容 扩容 缩容 引 言 随着金融领域分布式架构的转型升级&#xff0c;分布式数据库技术在金融领域应用逐步深入。为规范分布 式数据库技…