python编程-闭包

目录

一、闭包的概念

更深入理解闭包记住的环境信息

二、闭包的形成条件

1. 嵌套函数

关于嵌套函数的多种形式

2. 内部函数引用外部函数的变量

3. 外部函数返回内部函数

三、闭包的工作原理

内存中的具体存储结构

四、闭包的用途

1. 数据隐藏和封装

数据隐藏和封装的更多应用场景

2. 函数工厂

函数工厂的扩展应用

3. 延迟执行和回调函数

延迟执行和回调函数的深入应用

五、闭包的注意事项

1. 变量的生命周期和内存管理

方法一:将闭包函数返回值设置为 None

方法二:使用 del 关键字删除闭包函数及相关引用

方法三:重构代码,让闭包的生命周期更合理

变量的生命周期和内存管理的进一步讨论

2. 变量的可变性和作用域

变量的可变性和作用域的补充说明


一、闭包的概念

闭包是一种特殊的函数对象,它在函数定义的基础上,记住了定义它时所处的环境(即函数外部的变量及其取值等信息),即使在定义它的函数已经执行完毕之后,闭包函数仍然能够访问和操作这些外部环境中的变量。简单来说,闭包是由函数及其相关的引用环境组合而成的实体。

 

更深入理解闭包记住的环境信息

闭包所记住的定义它时所处的环境,不仅仅局限于简单的变量值,还包括变量的类型、所在的模块、甚至是函数调用时的上下文信息等。

例如,如果外部函数中定义的变量是一个来自特定模块的对象,闭包在后续执行时依然能够依据记住的模块信息正确地访问和操作该对象的属性与方法。

假设我们有以下代码:

import datetimedef outer_function():now = datetime.datetime.now()def inner_function():print(f"创建闭包时的时间是:{now}")return inner_functionclosure = outer_function()
closure()

在这个例子中,闭包记住了 now 这个 datetime.datetime 类型的对象,以及它来自 datetime 模块的信息,所以在调用闭包函数时能够正确地打印出创建闭包时的时间。

 

二、闭包的形成条件

要形成一个闭包,需要满足以下几个关键条件:

1. 嵌套函数

必须存在函数的嵌套定义,即一个函数内部定义了另一个函数。例如:

def outer_function():# 这里是外部函数的函数体def inner_function():# 这里是内部函数的函数体passreturn inner_function

在上述代码中,outer_function是外部函数,inner_function是在outer_function内部定义的内部函数,这种嵌套结构是形成闭包的基础。

 

关于嵌套函数的多种形式

除了常见的一层嵌套(即一个函数内部定义另一个函数),还可以存在多层嵌套的情况,形成更复杂的闭包结构。例如:

def outer_most_function():x = 10def middle_function():y = 20def inner_function():print(x + y)return inner_functionreturn middle_function()closure = outer_most_function()
closure()  # 输出:30

在上述代码中,outer_most_function 内部嵌套了 middle_function,而 middle_function 内部又嵌套了 inner_function,这种多层嵌套同样满足闭包的形成条件,并且内部的 inner_function 能够访问到外层函数定义的变量 x 和中层函数定义的变量 y

2. 内部函数引用外部函数的变量

内部函数需要引用外部函数中的变量。继续以上面的代码为例,假如我们在inner_function中引用了outer_function中的变量,如下所示:

def outer_function():x = 10def inner_function():print(x)return inner_function

在这里,inner_function引用了outer_function中定义的变量x,这是闭包能够 “记住” 外部环境的关键因素。

3. 外部函数返回内部函数

外部函数需要返回内部函数对象,使得在外部函数执行完毕后,内部函数仍然可以在其他地方被调用,并且保留对外部函数变量的访问能力。例如:

def outer_function():x = 10def inner_function():print(x)return inner_functionclosure = outer_function()
closure()

在这个例子中,outer_function返回了inner_function,然后我们将返回的函数对象赋值给closure变量,通过closure()就可以调用inner_function,此时即使outer_function的执行已经完成,inner_function依然能够访问x的值(这里会输出10)。

三、闭包的工作原理

当创建闭包时,Python 会在内存中创建一个特殊的结构来保存闭包的相关信息。具体来说:

  • 函数对象的创建:内部函数inner_function本身是一个函数对象,它包含了函数的代码逻辑、参数列表等常规函数属性。

  • 引用环境的保存:除了函数本身的属性,Python 还会保存内部函数所引用的外部函数变量的引用。在上面的例子中,当outer_function返回inner_function时,Python 会记住inner_function引用了outer_function中的变量x,并且会将这个引用关系与inner_function的函数对象一起保存起来。

  • 变量的访问机制:当后续调用闭包函数(如closure())时,Python 会根据保存的引用关系,在闭包的引用环境中查找被引用的变量。所以,即使outer_function已经执行结束,其内部定义的变量所在的内存空间可能已经在常规情况下被释放,但由于闭包保存了对这些变量的引用,这些变量仍然能够被闭包函数访问到,就好像它们仍然存在于一个特殊的 “闭包环境” 中一样。

内存中的具体存储结构

当创建闭包时,Python 在内存中创建的特殊结构类似于一个包含函数对象和其引用环境的 “包裹”。这个 “包裹” 会记录函数的代码对象(包含函数的定义、参数等信息)以及对外部变量的引用关系。

以之前的 outer_function 和 inner_function 为例,内存中的这个特殊结构会保存 inner_function 的代码对象以及它对 outer_function 中定义的变量 x 的引用信息。当调用闭包函数时,Python 会依据这个存储结构,先找到函数的代码对象来执行函数体,同时根据引用关系获取对应的外部变量值进行操作。

四、闭包的用途

闭包在 Python 编程中有多种用途,以下是一些常见的应用场景:

1. 数据隐藏和封装

闭包可以用于隐藏数据,使得外部无法直接访问某些变量,只有通过闭包函数提供的特定接口才能操作这些数据。例如:

def counter():count = 0def increment():nonlocal countcount += 1return countreturn incrementmy_counter = counter()
print(my_counter())  
print(my_counter())  

在这个例子中,count变量被封装在counter函数内部,外部无法直接访问它。只有通过increment函数(闭包)才能对count进行递增操作并获取其值,实现了一定程度的数据隐藏和封装

 

数据隐藏和封装的更多应用场景

  • 配置管理:在一些应用程序中,需要根据不同的配置参数来执行不同的操作,但又不想让这些配置参数被随意修改。闭包可以很好地实现这一点。例如:
def config_manager(config):def execute_task():if config["mode"] == "debug":print(f"以调试模式执行任务,参数:{config}")elif config["mode"] == "production":print(f"以生产模式执行任务,参数:{config}")return execute_taskdebug_config = {"mode": "debug", "param1": "value1"}
production_config = {"mode": "production", "param1": "value1"}debug_task = config_manager(debug_config)
production_task = config_manager(production_config)debug_task()
production_task()

在这个例子中,config 参数被封装在闭包内部,只有通过对应的闭包函数debug_task 和 production_task)才能根据不同的配置执行相应的任务,实现了配置参数的隐藏和封装。

 

  • 权限管理:闭包也可用于权限管理,限制对某些资源的访问。例如:
def access_manager(has_permission):def access_resource():if has_permission:print("有权限访问资源")else:print("无权限访问资源")return access_resourceuser1_access = access_manager(True)
user2_access = access_manager(False)user1_access()
user2_access()

这里,通过闭包函数 access_resource 根据传入的权限标志 has_permission 来决定是否有权限访问资源,实现了对资源访问权限的管理,并且 has_permission 这个变量被隐藏在闭包内部,外部无法直接修改它。

2. 函数工厂

闭包可以作为函数工厂,根据不同的输入参数生成具有不同行为的函数。例如:

def power_factory(exponent):def power(base):return base ** exponentreturn powersquare = power_factory(2)
cube = power_factory(3)print(square(5))  
print(cube(5))  

在这里,power_factory函数根据传入的exponent参数生成了不同的power函数(闭包)。square函数用于计算一个数的平方,cube函数用于计算一个数的立方,通过闭包实现了函数的动态生成

 

函数工厂的扩展应用

  • 动态生成验证函数:在表单验证等场景中,可以利用闭包生成不同的验证函数来检查输入数据是否符合特定的条件。例如:
def validation_factory(field_type):def validate(value):if field_type == "email":if "@" in value and "." in value:return Truereturn Falseelif field_type == "password":if len(value) >= 8:return Truereturn Falsereturn validateemail_validate = validation_factory("email")
password_validate = validation_factory("password")print(email_validate("test@example.com"))
print(password_validate("12345678"))

在这个例子中,validation_factory 根据传入的 field_type 参数生成不同的验证函数(闭包),用于验证不同类型的输入数据是否符合要求。

  • 生成特定格式的输出函数:闭包还可以用于生成按照特定格式输出数据的函数。例如:
def format_factory(format_str):def format_output(data):return format_str.format(data)return format_outputcurrency_format = format_factory("${0}")
percentage_format = format_factory("{0}%")print(currency_format(100))
print(percentage_format(0.5))

这里,format_factory 生成的闭包函数 format_output 能够根据传入的不同格式字符串将输入数据按照特定格式输出。

3. 延迟执行和回调函数

闭包可以用于实现延迟执行某些操作或者作为回调函数在特定事件发生时被调用。例如:

def delayed_execution(message):def execute():print(message)return executeaction = delayed_execution("这是延迟执行的消息")
action()

在这个例子中,delayed_execution函数返回的闭包execute可以在后续的某个时刻被调用,实现了消息的延迟打印,类似于设置了一个延迟执行的任务。在一些异步编程、事件驱动编程等场景中,闭包常被用作回调函数,在特定事件完成或满足一定条件时被触发执行。

 

延迟执行和回调函数的深入应用

  • 异步任务调度:在异步编程中,闭包常被用作回调函数来处理异步任务完成后的结果。例如:
import asyncioasync def async_task():await asyncio.sleep(2)return "异步任务完成"def callback_factory(result_callback):async def task_callback(task):result = await taskresult_callback(result)return task_callbackdef print_result(result):print(f"异步任务结果:{result}")callback = callback_factory(print_result)asyncio.run(async_task())
asyncio.run(callback(async_task()))

在这个例子中,callback_factory 生成的闭包函数 task_callback 作为回调函数,在异步任务 async_task 完成后,会调用传入的 result_callback 函数(这里是 print_result)来处理任务结果,实现了异步任务结果的处理和延迟执行(因为要等待异步任务完成后才执行回调函数)。

  • 事件驱动编程中的应用:在事件驱动编程中,闭拉常被用作回调函数,在事件发生时执行特定的操作。例如,在一个简单的图形界面应用程序中,当用户点击某个按钮时,会触发一个事件,我们可以使用闭包来定义在这个事件发生时要执行的操作。

假设我们有一个简单的按钮点击事件处理框架:

def button_click_handler_factory(action):def button_click_handler():action()return button_click_handlerdef print_message():print("按钮被点击了")handler = button_click_handler_factory(print_message)# 这里假设在图形界面应用程序中,当按钮被点击时,会调用handler函数
handler()

在这个例子中,button_click_handler_factory 生成的闭包函数 button_click_handler 作为按钮点击事件的处理函数,当按钮被点击时(假设在实际的图形界面应用程序中会触发调用这个函数),会执行传入的 action 函数(这里是 print_message),实现了在事件发生时的特定操作。

五、闭包的注意事项

在使用闭包时,也需要注意一些问题:

1. 变量的生命周期和内存管理

虽然闭包能够记住外部函数的变量,但如果不小心处理,可能会导致内存泄漏等问题。特别是当闭包函数长期存在并且不断引用一些大型数据结构或对象时,这些被引用的对象可能无法被正常垃圾回收,因为闭包一直保持着对它们的引用。例如:

def memory_leak_example():large_data = [i for i in range(1000000)]def closure_function():print(large_data)return closure_functionleak_closure = memory_leak_example()
# 这里如果不及时释放闭包引用,large_data可能一直占用内存空间,导致内存泄漏

为了避免这种情况,可以在适当的时候手动释放闭包对变量的引用,或者确保闭包的生命周期是合理的,不会导致不必要的内存占用。

 

方法一:将闭包函数返回值设置为 None

在使用完闭包函数后,将保存闭包函数的变量设置为 None,这样可以让 Python 的垃圾回收机制知道该闭包对象不再被使用,从而有可能回收其占用的内存,包括闭包内部引用的变量所占用的内存。

示例代码如下:

def memory_leak_example():large_data = [i for i in range(1000000)]def closure_function():print(large_data)return closure_functionleak_closure = memory_leak_example()
leak_closure()  # 调用闭包函数,此时会打印出 large_data# 将闭包函数引用设置为 None,以便垃圾回收机制回收内存
leak_closure = None

在上述代码中,通过 leak_closure = None 这一行,明确告知 Python 解释器 leak_closure 这个闭包对象不再被需要,从而给垃圾回收机制一个信号,让它在合适的时候回收闭包及其引用的变量所占用的内存空间。

 

方法二:使用 del 关键字删除闭包函数及相关引用

del 关键字可以用于删除对象的引用,当一个对象没有任何引用指向它时,Python 的垃圾回收机制会在适当的时候回收该对象占用的内存。

示例代码如下:

def memory_leak_example():large_data = [i for i in range(1000000)]def closure_function():print(large_data)return closure_functionleak_closure = memory_leak_example()
leak_closure()  # 调用闭包函数,此时会打印出 large_data# 使用 del 关键字删除闭包函数引用
del leak_closure# 也可以删除闭包函数内部引用的变量,如果在合适的上下文中
# del large_data (这里在示例函数中直接删除 large_data 可能会导致后续调用闭包函数出错,所以要根据具体情况谨慎使用)

在上述代码中,通过 del leak_closure 这一行,删除了对闭包函数的引用,使得闭包函数对象有可能被垃圾回收机制回收。需要注意的是,对于 large_data 变量,直接在示例函数外部删除它可能会导致后续如果再次调用闭包函数(虽然在这个示例中没有再次调用的情况,但在更复杂的场景下可能会有)时出错,因为闭包函数内部仍然引用着这个变量。所以是否删除 large_data 要根据具体的代码上下文和需求来决定。

方法三:重构代码,让闭包的生命周期更合理

有时候,通过重构代码的方式可以让闭包的生命周期更加合理,避免出现不必要的内存占用。

例如,在上述示例中,可以将 large_data 的生成和闭包函数的定义放在一个更小的作用域内,使得 large_data 在不需要的时候能够及时被销毁。

示例代码如下:

def memory_leak_example():def inner_function():large_data = [i for i in range(1000000)]def closure_function():print(large_data)return closure_functionreturn inner_function()leak_closure = memory_leak_example()
leak_closure()  # 调用闭包函数,此时会打印出 large_data# 这里因为 large_data 是在 inner_function 的作用域内定义的,当 inner_function 执行完毕后,
# large_data 的引用计数会减少,在合适的时候会被垃圾回收机制回收

在上述重构后的代码中,large_data 是在 inner_function 的作用域内定义的,当 inner_function 执行完毕后,large_data 的引用计数会减少,并且在合适的时候会被垃圾回收机制回收,而不需要像之前那样手动去释放闭包对 large_data 的引用,因为其生命周期已经更加合理,不会导致不必要的内存占用了。

 

变量的生命周期和内存管理的进一步讨论

  • 循环引用导致的内存问题:除了之前提到的闭包长期引用大型数据结构可能导致内存泄漏外,还可能出现循环引用的情况,进一步加重内存问题。例如:
def circular_reference_example():class MyClass:def __init__(self):self.closure = Nonemy_obj = MyClass()def outer_function():x = 10def inner_function():print(x)my_obj.closure = inner_functionreturn inner_functionclosure = outer_function()closure()# 这里形成了一个循环引用,my_obj引用了closure,而closure又引用了outer_function中的x,# 可能导致内存无法正常回收,即使不再使用closure,内存也不会释放

在这个例子中,my_obj 的 closure 属性指向了闭包函数 inner_function,而 inner_function 又引用了 outer_function 中的 x,形成了一个循环引用。这种情况下,即使后续不再使用 closure,由于循环引用的存在,内存可能无法正常回收。解决这种循环引用导致的内存问题,通常需要更加细致地管理对象的引用关系,比如在合适的时候将 my_obj.closure 设置为 None,或者使用一些垃圾回收辅助工具来检测和处理循环引用。

  • 不同版本 Python 对内存管理的影响:不同版本的 Python 在处理闭包和内存管理方面可能存在一些差异。例如,Python 2 和 Python 3 在某些情况下对闭包中变量的处理方式可能不同,这可能会影响到内存的使用和回收情况。在实际开发中,需要根据所使用的 Python 版本来关注这些差异,确保代码在不同版本上都能正常运行且不会出现内存相关的问题。

2. 变量的可变性和作用域

如果在闭包中引用的外部函数变量是可变的(如列表、字典等),在闭包函数内部对其进行操作时,需要注意可能会对外部函数的逻辑产生影响。例如:

def outer_function():my_list = [1, 2, 3]def inner_function():my_list.append(4)print(my_list)return inner_functionclosure = outer_function()
closure()
# 这里会修改外部函数中的my_list变量,可能会影响到依赖该变量原始状态的其他逻辑

在这种情况下,需要根据具体的需求来谨慎处理可变变量在闭包中的操作,以确保整个程序的逻辑正确性。同时,在闭包函数中如果需要修改外部函数中的非全局变量,可能需要使用nonlocal关键字来声明,以便明确告知 Python 要修改的是外部函数中的那个变量(如前面counter例子中的count变量)。

变量的可变性和作用域的补充说明

  • 全局变量在闭包中的影响:如果在闭包中引用了全局变量,并且在闭包函数内部对其进行了操作,同样需要注意可能会对整个程序的逻辑产生影响。例如:
count = 0def outer_function():def inner_function():global countcount += 1print(count)return inner_functionclosure = outer_function()
closure()
closure()

在这个例子中,闭包函数 inner_function 引用了全局变量 count,并且在内部对其进行了递增操作。这种情况下,由于全局变量是被整个程序共享的,所以在闭包中对其进行的任何操作都会影响到整个程序中依赖该变量的其他逻辑。因此,在使用闭包时,如果涉及到全局变量,需要特别谨慎地考虑其对整个程序的影响。

  • 使用 nonlocal 关键字的更多细节:当使用 nonlocal 关键字来声明要修改的外部函数中的非全局变量时,需要注意其适用范围。nonlocal 关键字只能用于声明已经存在于外层函数中的变量,并且不能用于声明全新的变量。例如:
def outer_function():x = 10def inner_function():nonlocal xx += 1print(x)return inner_functionclosure = outer_function()
closure()
closure()

在这个例子中,nonlocal x 声明了要修改的是外层函数 outer_function 中的变量 x,并且可以正常地对其进行修改。但是,如果在 inner_function 中尝试使用 nonlocal 关键字来声明一个全新的变量,比如 nonlocal y(假设 y 之前未在任何外层函数中定义),将会抛出异常,因为 nonlocal 关键字不支持这种用法。

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

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

相关文章

【EndNote版】如何在Word中引用文献

1、在Word中,鼠标光标放在所需插入文献的位置 2、点击选项卡中的“EndNote X9”,直接在EndNote中选中对应的文献 3、选中文献,点击工具栏中的“引用” 4、最后就可在Word中看到所插入的文献

华为配置BFD状态与接口状态联动实验

组网图形 图1 配置BFD状态与接口状态联动组网图 BFD简介配置注意事项组网需求配置思路操作步骤配置文件 BFD简介 为了减小设备故障对业务的影响,提高网络的可靠性,网络设备需要能够尽快检测到与相邻设备间的通信故障,以便及时采取措施&…

技术成神之路:设计模式(二十三)解释器模式

相关文章:技术成神之路:二十三种设计模式(导航页) 介绍 解释器模式(Interpreter Pattern)是一种行为设计模式,用于定义一种语言的文法表示,并提供一个解释器来处理这种文法。它用于处理具有特定语法或表达…

【C++】继承与模板

继承 1.继承的概念 概念:继承(inheritace)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称之为派生类。继承呈现了面向对象程序设计的…

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解 目录 时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (创新独家)TTNRBO-VMD改进牛顿-拉夫逊优化算优化变分模态分解TTNRBO–VMD 优化VMD分解层数K和…

设计模式-单例模型(单件模式、Singleton)

单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。 单例模式同时解决了两个问题, 所以违反了单一职责原则: 保证一个类只有一个实例。 为什么会有人想要控制一个类所拥有的实例…

【Java并发编程】信号量Semaphore详解

一、简介 Semaphore(信号量):是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。 Semaphore 一般用于流量的控制,特别是公共资源有限的应用场景。例如数据库的连接&am…

谈谈对函数式编程的理解及rxjs的使用

背景 函数式编程可以说是非常古老的编程方式,但是近几年变成了一个非常热门的话题。不管是Google力推的Go、学术派的Scala与Haskell,还是Lisp的新语言Clojure,这些新的函数式编程语言越来越受到人们的关注。函数式编程思想对前端的影响很大&…

C语言基础题(大合集2)

1. 时间转换 给定秒数 --> 输出秒数 转化成 时/分/秒 //时间转换 //给定秒数 --> 转换成 小时/分/秒 int main() {//输入int seconds 0;int h 0;//小时int m 0;//分钟int s 0;//秒scanf("%d", &seconds);//计算h seconds / 60 / 60;m seconds / 60…

详解varint,zigzag编码, 以及在Go标准库中的实现

文章目录 为啥需要varint编码为啥需要zigzag编码varint编码解码 zigzag编码解码 局限性 为啥需要varint编码 当我们用定长数字类型int32来表示整数时,为了传输一个整数1,我们需要传输00000000 00000000 00000000 00000001 32 个 bits,而有价…

【C++】STL初识

【C】STL初识 文章目录 【C】STL初识前言一、STL基本概念二、STL六大组件简介三、STL三大组件四、初识STL总结 前言 本篇文章将讲到STL基本概念,STL六大组件简介,STL三大组件,初识STL。 一、STL基本概念 STL(Standard Template Library,标准…

QT建立工程时出现了:Reading Project

QT建立工程时出现了:Reading Project 打开建立的工程发现,缺少build文件 从别的工程中复制一个build,点击.pro就可以打开了

【CSS3】css开篇基础(4)

1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…

Spring Boot实现的动态化酒店住宿管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理酒店客房管理系统的相关信息成为必然。开发…

图文详解ChatGPT-o1完成论文写作的全流程

学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 本月中旬OpenAI发布了OpenAI o1系列新的AI模型。 据OpenAI介绍,这些模型旨在花更多时间思考后再做出反应,就像人一样。通过训练,它们学会改进思维过…

深度学习(六)CNN:图像处理的强大工具(6/10)

一、CNN 的概述 卷积神经网络(Convolutional Neural Networks,CNN)是深度学习的代表算法之一,在深度学习中占据着重要地位。 CNN 的发展历程可追溯至 20 世纪 80 至 90 年代,时间延迟网络和 LeNet - 5 是最早出现的卷…

conda虚拟环境中安装cuda方法、遇到的问题

conda虚拟环境中安装cuda方法、遇到的问题 文章目录 conda虚拟环境中安装cuda方法、遇到的问题conda虚拟环境中安装cudacuda.h和cuda_runtime.hpytorch运行时的CUDA版本其他问题检查包冲突nvcc -V和nvidia-smi显示的版本不一致cuda路径 conda虚拟环境中安装cuda 参考文章&…

【AIGC】从CoT到BoT:AGI推理能力提升24%的技术变革如何驱动ChatGPT未来发展

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯迈向AGI的新跨越💯BoT与CoT的技术对比技术原理差异推理性能提升应用范围和通用性从错误中学习的能力总结 💯BoT的工作流程和机制初始化过程生成推…

layaair获取组件里的脚本

获取脚本用getComponents方法,但是这个方法里的参数不是脚本的名称。而是组件类型。如果你需要获取脚本,则类型为Laya.Script。挺坑的。我在官网找都没找到这个是这么用的。我猜测的。没想到试了一下成功了。 property(Laya.Node)public img1: Laya.Node…

碰一碰支付系统搭建怎么做?头部公司源码大测评!

随着碰一碰支付dai li骗局的曝光,越来越多的人开始选择将目光转向碰一碰支付系统搭建这一入局方式,连带着与之相关的多个话题,如碰一碰支付系统搭建怎么做等也成为了当前的一大热点。 毕竟,相较于dai li 模式的与第三方公司合作、…