【Python学习手册(第四版)】学习笔记20.2-迭代和解析(二)-迭代解析、迭代方法的计时比较、函数陷阱

个人总结难免疏漏,请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。

本文较简单,主要是概括了解析语法(列表解析、生成器、集合、字典解析),以及对前面的各种迭代进行计时比较,编写计时模块,测试计时脚本,优化模块方案,最后介绍了函数陷阱,如本地变量检测、默认和可变对象、没有return等,结束了函数部分。


目录

解析语法概括

解析集合和字典解析

集合、字典扩展的解析语法

对迭代的各种方法进行计时

编写计时模块

计时脚本

计时结果

计时模块替代方案

函数陷阱

本地变量是静态检测的

默认和可变对象

没有return语句的函数

嵌套作用域的循环变量


解析语法概括

除了列表解析和生成器,还有两种在Python 3.0中可用的解析表达式形式:集合解析和字典解析。

  • 对于集合,新的常量形式{1,3,2}等同于set([1,3,2]),并且新的集合解析语法{f(x)for x in S if P(x)}就像是生成器表达式set(f(x)for x in S if P(x)),其中f(x)是一个任意的表达式。
  • 对于字典,新的字典解析语法{key:val for(key,val)in zip(keys,vals)}像dict(zip(keys,vals))形式一样工作,并且{x:f(x)for x in items}像生成器表达式dict((x,f(x))for x in items)一样工作。

这是所有解析替代方式的总结

[x * x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81](x * x for x in range(10))
<generator object <genexpr> at 0x000001DA221F9A40>{x * x for x in range(10)}
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}{x:x * x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

解析集合和字典解析

从某种意义上讲,集合解析和字典解析只是把生成器表达式传递给类型名的语法糖。因此,二者都接受任何的可迭代对象,一个生成器在这里工作得很好。

{x * x for x in range(10)}
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
set(x * x for x in range(10))
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}{x:x * x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
dict((x,x * x) for x in range(10))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

对于列表解析来说,总是可以用手动代码来构建结果对象。这里是最后两个解析的基于语句的等价形式。

注意,尽管这两种形式都接受迭代器,它们没有根据需要产生结果的概念——两种形式都是一次构建所有对象。如果你想要根据需求产生键和值,生成器表达式更合适。

G = ((x,x * x) for x in range(10))
next(G)
(0, 0)
next(G)
(1, 1)

集合、字典扩展的解析语法

和列表解析及生成器表达式一样,集合和字典解析都支持嵌套相关的if子句从结果中过滤掉元素——如下的代码收集一个范围内的每个元素的平方(例如,元素被2除没有余数)。

嵌套的for循环也有效,尽管两种类型的对象无序的和无副本的特性可能会使得结果看上去缺乏直接性。

和列表解析一样,集合解析和字典解析也可以在任何类型的可迭代对象上迭代——列表、字符串、文件、范围以及支持迭代协议的任何其他类型。


对迭代的各种方法进行计时

简要地看一下这个实例,来学习融和了所有我们所学过的关于迭代和函数的内容。

列表解析要比for循环语句有速度方面的性能优势,而且map会依据调用方法的不同表现出更好或更差的性能。上一节介绍的生成器表达式看起来比列表解析速度更慢一些,但是它们把内存需求降到了最小。

随着时间的不同其相对的性能也有所不同(Python还在不断的优化中)。试试在自己的电脑上,用现有的Python版本来运行下面脚本,自己测试它们。

编写计时模块

Python使得对代码计时变得很容易。要看看迭代选项是如何叠加起来的,从编写到一个模块文件中的简单但通用的计时器工具函数开始,从而使其可以用于各类程序中。

reps = 10000
repslist = range(reps)def timer(func, *pargs, **kargs):start = time.process_time()for i in repslist:ret = func(*pargs, **kargs)elapsed = time.process_time() - startreturn (elapsed, ret)

这个模块通过获取开始时间、调用函数固定的次数并且用开始时间减去停止时间,从而对使用任何位置和关键字参数调用任意函数进行计时。注意以下几点:

·Python的time模块允许访问当前时间,精度随着每个平台而有所不同。在Windows上,这个调用号称能够达到微妙的精度,已经相当准确了。

这里原书中用的是time.clock(),这个函数在 Python 3.3 中被废弃,并在 Python 3.8 中被彻底删除。这里采用的是time.process_time(),函数用于返回当前系统的高精度性能计数器的值,返回一个浮点数,表示自程序运行以来经过的时间。

·range调用放到了计时循环之外,在Python 3.0的range是一个迭代器,因此这个步骤是不需要的(但无伤大雅)。

·reps计数是一个全局变量,如果需要的话,导入者可以修改它:mytimer.reps=N。

当这些完成后,所有调用的总的使用时间在一个元组中返回,还带有被计时的函数的最终返回值,以便调用者可以验证其操作。

从一个更大的角度来看,由于这个函数编写到一个模块文件中,在我们想要导入它的任何地方,它都成为了一个广为有用的工具。后面可以直接导入该模块并调用函数来使用这个文件的计时器。

计时脚本

要计时迭代工具的速度,运行如下的脚本,它使用刚刚编写来统计已经学习过的各种列表构建技术的相对速度的计时器模块。

import sys
reps = 10000
repslist = range(reps)def foorloop():res = []for x in repslist:res.append(abs(x))return resdef listcomp():return [abs(x) for x in repslist]def mapcall():return list(map(abs, repslist))def genexpr():return list(abs(x) for x in repslist)def genfunc():def gen():for x in repslist:yield abs(x)return list(gen())print(sys.version)
for test in (foorloop, listcomp, mapcall, genexpr, genfunc):elapsed, result = timer(test)print('-' * 33)print('%-9s:%.5f=>[%s...%s]' %(test.__name__, elapsed, result[0], result[-1]))

这段脚本测试了五种构建结果列表的替代方法,五个测试中的每一个都构建了拥有10000个元素的列表10000次。

必须通过内置的list调用来运行生成器表达式和函数结果,从而迫使它们产生其所有的值;如果没有这么做,可能会得到并没有真正工作的生成器。

底部的代码遍历4个函数对象的一个元组并打印出每一个的__name__。这是一个内置的属性,它给出函数的名称。

计时结果

3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)]
---------------------------------
foorloop :2.57812=>[0...9999]
---------------------------------
listcomp :1.79688=>[0...9999]
---------------------------------
mapcall  :1.64062=>[0...9999]
---------------------------------
genexpr  :3.76562=>[0...9999]
---------------------------------
genfunc  :3.59375=>[0...9999]

如果研究这些代码及其输出足够长的时间,将会注意到,生成器表达式比列表解析运行得慢。尽管把一个生成器表达式包装到一个list调用中,会使得其功能等同于一个带有方括号的列表解析,两种表达式的内部实现看上去有所不同(尽管已经实际地对生成器测试的列表调用计时)。

如果修改这段脚本,在每次迭代上执行一个真正的操作(如加法),而不是调用abs这样的小的内置函数,看看会发生什么(如下代码中省略的部分与前面相同)。

def foorloop():res = []for x in repslist:res.append(x + 10)return resdef listcomp():return [x + 10 for x in repslist]def mapcall():return list(map((lambda x:x + 10), repslist))def genexpr():return list(x + 10 for x in repslist)def genfunc():def gen():for x in repslist:yield x + 10return list(gen())

如果需要针对map调用来调用一个用户定义的函数,会使它比for循环语句慢,尽管循环语句的版本的代码更多。

3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)]
---------------------------------
foorloop :2.53125=>[10...10009]
---------------------------------
listcomp :2.31250=>[10...10009]
---------------------------------
mapcall  :4.56250=>[10...10009]
---------------------------------
genexpr  :3.75000=>[10...10009]
---------------------------------
genfunc  :3.25000=>[10...10009]

由于解释器优化是如此内部化的一个问题,像这样对Python代码进行性能分析是一件非常需要技术的事情。事实上不可能猜测哪种方法会执行的最好,最好的办法是在自己的计算机上、用自己的Python版本,对自己的代码计时。

在这种情况下,可以肯定地说的是,在这个Python版本下,在map调用中使用一个用户定义的函数至少会因为两种因素中的一种而执行较慢,并且列表解析对于这一测试运行最快。

性能应该不是编写Python代码时首要关心的问题——要优化Python代码,应该做的第一件事情就是不要优化Python代码!

首先为了可读性和简单性而编写代码,然后,如果需要的话并且只有在需要的时候,再优化。如果对于你的程序需要处理的数据集合来说,五种替代方案中的任何一种足够快,这将是很好的事情;如果是这样的话,程序的清晰性应该是首要的目标。

计时模块替代方案

前面小节介绍的计时模块是有效的,但是,它在多个方面还有些简单:

  • 调整重复的次数需要修改模块级别的全局变量——如果要使用timer函数并且有多个导入者共享的话,这是不太理想的安排。
  • 计时器必须通过运行测试函数很多次才能工作。要考虑随机的系统载入的波动,在所有的测试中选择最好的时间,而不是总的时间,可能会更好。

如下的替代实现了一种更为高级的计时器模块,允许重复计数作为一个名为_reps的关键字参数传入,并且提供N中最好的一个替代计时函数。

这里采用了keyword-only参数

import time
trace = lambda *args: Nonedef timer(func, *pargs, _reps = 1000,**kargs):trace(func, pargs, kargs, _reps)    #说实话把这句去掉感觉也无差异,可能是本人水平较低start = time.process_time()for i in range(_reps):ret = func(*pargs, **kargs)elapsed = time.process_time() - startreturn (elapsed, ret)def best(func,*pargs,_reps=50, **kargs):best = 2 ** 32for i in range(_reps):(time,ret) = timer(func,*pargs, _reps= 1, **kargs)if time < best : best = timereturn (best,ret)

位于文件顶部的这个模块的文档字符串描述了模块的目标用途。它使用字典的pop操作,从用于测试函数的参数中删除_reps参数并为其提供一个默认值,并且,如果你将其trace函数修改为print的话,它会在开发过程中跟踪参数。

import sys,mytimerreps = 10000
repslist = range(reps)def foorloop():res = []for x in repslist:res.append(x + 10)return resdef listcomp():return [x + 10 for x in repslist]def mapcall():return list(map((lambda x:x + 10), repslist))def genexpr():return list(x + 10 for x in repslist)def genfunc():def gen():for x in repslist:yield x + 10return list(gen())print(sys.version)
for tester in (mytimer.timer,mytimer.best):print('<%s>' % tester.__name__)for test in (foorloop, listcomp, mapcall, genexpr, genfunc):elapsed, result = mytimer.timer(test)print('-' * 33)print('%-9s:%.5f=>[%s...%s]' %(test.__name__, elapsed, result[0], result[-1]))

计时结果基本与前面相同,并且对于N个之和与N中最好的计时技术来说相对都是相同的——多次运行测试似乎做了很好的工作来过滤掉系统载入波动而采取最好的情况,但是,当测试一个长时间运行的函数的时候,N中最好的方案可能更好。

如果你的程序在较大的数据集合上迭代很多次的话,它可能变得很显著。至少在相对性能方面,列表解析在大多数情况下表现最好。当使用内置函数时,map表现更好。

<timer>
---------------------------------
foorloop :0.12500=>[10...10009]
---------------------------------
listcomp :0.23438=>[10...10009]
---------------------------------
mapcall  :0.46875=>[10...10009]
---------------------------------
genexpr  :0.37500=>[10...10009]
---------------------------------
genfunc  :0.34375=>[10...10009]
<best>
---------------------------------
foorloop :0.25000=>[10...10009]
---------------------------------
listcomp :0.32812=>[10...10009]
---------------------------------
mapcall  :0.21875=>[10...10009]
---------------------------------
genexpr  :0.25000=>[10...10009]
---------------------------------
genfunc  :0.20312=>[10...10009]

计时器的结果可以帮助我们判断代码替代方案的相对速度,并且可能对于如下这样较长时间运行的操作更有意义——计算2的一百万次方比前面的2**100000要长一个量级(10倍)。

如果想要比较2.X和3.X的速度,或者支持使用任意一种Python版本的程序员,较早的版本可能是更好的选择。


函数陷阱

来看一些常见的陷阱。函数有些你想不到的陷阱。它们都很少见,而有些在最新版本中已经从语言中完全消失,但多数都会让新的用户栽跟头。

本地变量是静态检测的

Python定义的在一个函数中进行分配的变量名是默认为本地变量的,它们存在于函数的作用域并只在函数运行时存在。Python是静态检测Python的本地变量的,当编译def代码时,不是通过发现赋值语句在运行时进行检测的。这导致了在Python入门者最为常见的陷阱之一。

一般来说,没有在函数中赋值的变量名会在整个模块文件中查找。

这里,函数中的X被解析为模块中的X。但是如果在引用之后增加了一个赋值语句

def sec():print(x)aa = 88sec()
Traceback (most recent call last):File "<pyshell#193>", line 1, in <module>sec()File "<pyshell#192>", line 2, in secprint(x)
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value

得到了一个未定义变量名的错误。

在交互模式下输入或从一个模块文件中导入时,Python读入并编译这级代码。在编译时,Python看到了对X的赋值语句,并且决定了X将会在函数中的任一地方都将是本地变量名。

但是,当函数实际运行时,因为在print执行时赋值语句并没有发生,Python告诉你正在使用一个未定义的变量名。根据其变量名规则,本地变量X是在其被赋值前就使用了。实际上,任何在函数体内的赋值将会使其成为一个本地变量名。Import、=、嵌套def、嵌套类等,都会受这种行为的影响。

产生这种问题的原因在于被赋值的变量名在函数内部是当作本地变量来对待的,而不是仅仅在赋值以后的语句中才被当做是本地变量。

实际上,前一个例子是最含糊不清的:是希望打印一个全局变量X之后创建一个本地变量X,还是这真的是一个程序错误?因为Python会在函数中将X作为本地变量,它就是一个错误。如果你真的想要打印全局变量X,需要在一个global语句中声明这一点。

尽管这样,这一位置的赋值语句同样会改变全局变量X,而不是一个本地变量。在函数中,不可能同时使用同一个简单变量名的本地变量和全局变量。如果真的是希望打印全局变量,并在之后设置一个有着相同变量名的本地变量,导入上层的模块,并使用模块的属性标记来获得其全局变量。

点号运算(.X这部分)从命名空间对象中获取了变量的值。交互模式下的命名空间是一个名为__main__的命名空间,所以__main__.X得到了全局变量版本的X。

默认和可变对象

默认参数是在def语句运行时评估并保存的,而不是在这个函数调用时。从内部来讲,Python会将每一个默认参数保存成一个对象,附加在这个函数本身。

因为默认参数是在def时被评估的,如果必要的话,它能够从整个作用域内保存值,但是因为默认参数在调用之间都保存了一个对象,必须对修改可变的默认参数十分小心。

例如,下面的函数使用了一个空列表作为默认参数,并在函数每次调用时都对它进行了改变。

有些人把这种行为当作一种特性。因为可变类型的默认参数在函数调用之间保存了它们的状态,从某种意义上讲它们能够充当C语言中的静态本地函数变量的角色。在一定程度上,它们工作起来就像全局变量,但是它们的变量名对于函数来说是本地变量,而且不会与程序中的其他变量名发生冲突。

尽管这样,对于大多数人来说,这看起来就像是一个陷阱,特别第一次遇到这样的情况的时候。

在Python中有更好的办法在调用之间保存状态(例如,使用类)

此外,可变类型默认参数记忆起来比较困难(理解起来也不容易)。它们的值取决于默认对象构建的时间。

在上一个例子中,其中只有一个列表对象作为默认值,这个列表对象是在def语句执行时被创建的。不会每次函数调用时都得到一个新的列表,所以每次新的元素加入后,列表会变大,对于每次调用,它都没有重置为空列表。

如果这不是你想要的行为的话,在函数主体的开始对默认参数进行简单的拷贝,或者将默认参数值的表达式移至函数体内部。只要值是存在于在代码中,而这部分代码在函数每次运行时都会执行的话,你就会每次都得到一个新的对象。

这个例子中的if语句可以被赋值语句x=x or[]来代替,这个赋值语句将会利用Python的or语句返回操作符对象中的一个的特性:如果没有参数传入的话,x将会默认为None,所以or将会返回右边的空列表。

尽管如此,这还不是完全相同的。如果是一个空列表被传入,or表达式将会导致函数扩展并返回一个新创建的列表,而不是像if版本那样扩展并返回传入的列表。(表达式变成[]or[],将会设置为右边空列表的值。

以一种较少令人混淆的方式来实现可变默认值效果的另一种方式,

该函数的名称对于函数自身来说是全局的,但是,它不需要声明,因为它在函数内部是不会直接修改的。这并不是总是以完全相同的方式使用,但是,当这样编写代码的时候,一个对象到函数的附加总是更加明确(并且肯定更容易理解)。

没有return语句的函数

在Python函数中,return(以及yield)语句是可选的。当一个函数没有精确的返回值的时候,函数在控制权从函数主体脱离时,函数将会退出。从技术上来讲,所有的函数都返回了一个值,如果没有提供return语句,函数将自动返回None对象:

没有return语句的函数与Python对应于一些其他语言中所谓的“过程”是等效的。它们常被当作语句,并且None这个结果被忽略了,就像它们只是执行任务而不需要计算有用的结果一样。

如果你想要尝试使用一个没有返回值的函数的结果时,Python不会告诉你。

例如,将一个列表添加方法的结果赋值不会导致错误,但是得到的会是None,而不是改变后的列表。

这样的函数执行任务也会有副作用,就是它们往往设计成语句来运行,而不是表达式。

嵌套作用域的循环变量

在进行嵌套函数作用域查找时,处理嵌套的循环改变了的变量时要小心。所有的引用将会使用在最后的循环迭代中对应的值。作为替代,请使用默认参数来保持循环变量的值。

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

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

相关文章

漂亮的业绩,重挫的股价,快手“遭遇”了什么?

现象与本质往往背道而驰&#xff0c;如同威廉莎士比亚形容的那般&#xff0c;“表面的平静可能掩盖了深深的波澜。”这一真理不仅充斥在生活中的各个片段&#xff0c;也散布在市场的每一个瞬间。 近日发布二季度财报的快手就迎来了“两级反转”。多项核心业绩指标录得增幅的同…

云计算产业链图谱_产业链全景图_云计算行业市场分析

在产业数字化转型的背景下&#xff0c;云计算作为信息技术的重要组成部分&#xff0c;正逐渐成为各行业数字化、智能化转型的关键支撑。受益于5G、大数据、物联网、人工智能等技术的快速发展&#xff0c;云计算产业规模持续扩大&#xff0c;市场需求不断增长。云计算作为一种新…

网络安全教程初级简介

随着技术的发展和信息池的增加&#xff0c;信息系统迫切需要建立网络安全措施&#xff0c;以保护输入这些系统的信息。网络安全是任何组织&#xff08;从小型初创公司到大型跨国组织&#xff09;的必备条件。 网络安全包括一系列技术、流程和实践&#xff0c;用于保护网络、设…

【Kotlin设计模式】Kotlin实现工厂模式

前言 工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;提供一个创建对象的接口&#xff0c;不暴露对象的创建过程。它将实例化对象的任务交给子类或具体实现&#xff0c;从而使得客户端代码与具体类解耦。 工厂模式主要分为以下三类&#xf…

音乐剪辑软件哪个好用?免费音乐编辑软件大推荐

在音符跳跃的创意海洋里&#xff0c;每一段旋律都藏着一个故事等待被精心雕琢。 但何以让这份灵感自由翱翔&#xff0c;又无需负担昂贵的工具枷锁&#xff1f;哪款音乐剪辑软件免费版能够成为你音乐创作旅程中的最佳拍档&#xff1f; 在这五彩斑斓的数字音频世界中&#xff0…

硬件面试经典 100 题(81~90)题

81、请问下图电路中二极管 D1、D2 有什么作用&#xff1f; 在 Vi 输入电压接近于零时&#xff0c;D1、D2 给三极管 T1、T2 提供偏置电压&#xff0c;使 T1、T2 维持导通&#xff0c;以消除交越失真。 陈氏解释 这道题参见&#xff1a;硬件面试经典 100 题&#xff08;51~70 题…

Nginx 反向代理实现 Tomcat 高可用性负载均衡详解

Tomcat 简介 Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun和其他一些公司及个人共同开发而成。 Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用服务…

【OpenCV】 中使用 Lucas-Kanade 光流进行对象跟踪和路径映射

文章目录 一、说明二、什么是Lucas-Kanade 方法三、Lucas-Kanade 原理四、代码实现4.1 第 1 步&#xff1a;用户在第一帧绘制一个矩形4.2 第 2 步&#xff1a;从图像中提取关键点4.3 第 3 步&#xff1a;跟踪每一帧的关键点 一、说明 本文针对基于光流法的目标追踪进行叙述&am…

影响我国地理信息产业发展最大的阻碍是?

我国地理信息产业发展迅速&#xff0c;大家可以从业内协会领导或院士报告中了解相关数据&#xff0c;每年地理信息产业规模多少多少亿&#xff0c;增长多少多少百分比&#xff0c;在成绩喜人的同时&#xff0c;当然专家或院士从更高层面分析了当前地理信息产业所遇到的困难与阻…

如何使用ssm实现基于ssm的“游侠”旅游信息管理系统

TOC ssm190基于ssm的“游侠”旅游信息管理系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#x…

如何用Java SpringBoot和Vue搭建高效的OA办公管理系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Leetcode 46.全排列

注意的点&#xff1a; 1、回溯本质就是搜索树的树枝&#xff0c;维护三个核心变量&#xff1a;path&#xff08;需要恢复现场&#xff09;&#xff0c;visited&#xff08;需要恢复现场&#xff09;&#xff0c;以及res 解法&#xff1a;回溯算法 class Solution:def permut…

linux死锁问题和cpu使用率过高问题排查

1、问题共同点 死锁问题和cpu使用率过高都是需要我们找出对应的问题线程。 死锁问题需要我们找出哪两个线程出现了死锁情况。 cpu使用率过高需要我们找出哪个或哪些线程占用了大量的cpu。 2、命令排查 2.1、查看机器上的Java进程 jcmd或 jps2.2、查看对应Java进程的线程级别…

简单的jar包重打包Failed to get nested archive for entry 报错处理

简单的jar包重打包Failed to get nested archive for entry 报错处理 1. 需求 公司有一个后端项目&#xff0c;项目已经打好了jar包&#xff0c;现在我们发现jar包依赖的子包有问题&#xff0c;其中的一个mybatis xml文件查询数据不正确&#xff0c;我们需要替换项目&#xf…

Java语言程序设计基础篇_编程练习题*17.4 (将文本文件转換为UTF格式)

目录 题目&#xff1a;*17.4 (将文本文件转換为UTF格式) 习题思路 代码示例 输出结果 题目&#xff1a;*17.4 (将文本文件转換为UTF格式) 编写一个程序&#xff0c;每次从文本文件中读取多行字符&#xff0c;并将这些行字符以UTF-8字符串格式写入一个二进制文件中…

Jenkins 2.346.1完整搭建及项目部署安装

java version "1.8.0_202" 1.安装 官网下载war包直接启动&#xff0c;比较简单&#xff0c; linux命令 &#xff1a; wget https://mirrors.jenkins.io/war-stable/2.346.1/jenkins.war 2.启动命令 nohup java -jar jenkins.war --httpPort8777 --prefix/jenkin…

整套厨帽检测算法样本、模型、源码和厨帽算法识别应用方案介绍

厨帽检测算法的应用方案主要涉及技术选型、硬件配置、软件集成、部署与监控以及应对实际挑战等多个方面。以下是一个详细的应用方案概述&#xff1a; 一、技术选型 深度学习技术&#xff1a;厨帽检测算法主要基于深度学习技术&#xff0c;特别是卷积神经网络&#xff08;CNN&…

“解锁进程间高效沟通,Linux IPC是你的关键钥匙!“#Linux系统编程之进程间通信【下】

"解锁进程间高效沟通&#xff0c;Linux IPC是你的关键钥匙&#xff01;"#Linux系统编程之进程间通信【下】 前言预备知识一、 共享内存概述1.1 共享内存概述简图 二、 共享内存编程实战2.1 共享内存介绍2.1.1 共享内存的特点 2.2 共享内存几个重要API介绍2.2.1 shmge…

三品船舶PLM解决方案详情 三品PLM软件在船舶制造行业应用优势

自2024年起&#xff0c;船舶行业PLM&#xff08;产品全生命周期管理&#xff09;技术步入关键发展阶段。国产化工业软件领域积极倡导生态合作&#xff0c;推广统一技术底座下的合作开发模式&#xff0c;整合国内外成熟的工业软件技术与应用资源&#xff0c;旨在全面提升国内船舶…

webflux源码解析(3)-reactor netty

目录 1.连接的状态2.reactor netty中的连接状态3. webflux中的io处理4.总结 为什么webflux在io密集型的场景能有效的提升系统吞吐量呢&#xff1f; 是因为它使用的是响应式编程&#xff0c;使用的是NIO&#xff0c;但这里的响应式、nio到底是怎么样的呢&#xff1f;响应式编程上…